fix: Home Assistant: map emergency_heating system mode to heat (#33453)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Fergal CondronandClaude Opus 5.5 authored and GitHub committed 2026-10-20 17:57:46 +02:00
1 parent f152398c9d
commit 8e4b2cba06
2 files changed
+40

No files matched your search

+10
View File
@@ -775,6 +775,16 @@ export class HomeAssistant extends Extension {
discoveryEntry.discovery_payload.mode_state_topic = true;
discoveryEntry.discovery_payload.mode_state_template = stateValueTemplate(mode.property);
discoveryEntry.discovery_payload.modes = mode.values;
if (mode.values.includes("emergency_heating")) {
// 'emergency_heating' (e.g. Hive SLR boost) is not a valid Home Assistant HVAC mode,
// reporting it would make Home Assistant reject every state update. Report it as 'heat'
// and don't offer it as a mode; it can still be set via MQTT or the frontend.
discoveryEntry.discovery_payload.mode_state_template = stateValueTemplate(
mode.property,
`{% set mode = value_json["${mode.property}"] %}{{ 'heat' if mode == 'emergency_heating' else mode }}`,
);
discoveryEntry.discovery_payload.modes = mode.values.filter((v) => v !== "emergency_heating");
}
discoveryEntry.discovery_payload.mode_command_topic = true;
}
+30
View File
@@ -1876,6 +1876,36 @@ describe("Extension: HomeAssistant", () => {
expect(climate!.discovery_payload).not.toHaveProperty("temperature_high_command_topic");
});
it("Should map emergency_heating to heat for climate", () => {
const climateExpose = new zhc.Climate()
.withSetpoint("occupied_heating_setpoint", 5, 32, 0.5)
.withLocalTemperature()
.withSystemMode(["off", "auto", "heat", "emergency_heating"])
.withEndpoint("water");
const device = {
definition: {},
isDevice: (): boolean => true,
isGroup: (): boolean => false,
endpoint: () => undefined,
options: {},
exposes: (): zhc.Expose[] => [climateExpose],
zh: {endpoints: []},
} as Device;
// @ts-expect-error private
const configs = extension.getConfigs(device);
const climate = configs.find((c) => c.type === "climate" && c.object_id === "climate_water");
expect(climate).toBeDefined();
expect(climate!.discovery_payload.modes).toStrictEqual(["off", "auto", "heat"]);
expect(climate!.discovery_payload.mode_state_template).toStrictEqual(
`{% if "system_mode_water" in value_json %}{% set mode = value_json["system_mode_water"] %}{{ 'heat' if mode == 'emergency_heating' else mode }}{% endif %}`,
);
// Expose itself is untouched so other consumers (e.g. frontend) can still use emergency_heating
expect(climateExpose.features.find((f) => f.name === "system_mode")).toMatchObject({
values: ["off", "auto", "heat", "emergency_heating"],
});
});
it("Should discover devices with cover_position", () => {
let payload;