fix: Improve Home Assistant cover state discovery

This commit is contained in:
Michal Feix
2026-08-26 12:08:50 +02:00
committed by Koen Kanters
parent 7fbbbc3b17
commit c867ca5182
2 changed files with 29 additions and 3 deletions
+15 -1
View File
@@ -987,6 +987,9 @@ export class HomeAssistant extends Extension {
// If curtains have `motor_state` or `moving` property, lookup for possible
// state names to detect movement direction and use this in discovery.
if (motorState) {
const motorStateProperty = featurePropertyWithoutEndpoint(motorState);
const stateProperty = featurePropertyWithoutEndpoint(state);
const openingState = motorState.values.find((s) => COVER_OPENING_LOOKUP.includes(s.toString().toLowerCase()));
const closingState = motorState.values.find((s) => COVER_CLOSING_LOOKUP.includes(s.toString().toLowerCase()));
const stoppedState = motorState.values.find((s) => COVER_STOPPED_LOOKUP.includes(s.toString().toLowerCase()));
@@ -994,8 +997,19 @@ export class HomeAssistant extends Extension {
if (openingState && closingState && stoppedState) {
discoveryEntry.discovery_payload.state_opening = openingState;
discoveryEntry.discovery_payload.state_closing = closingState;
discoveryEntry.discovery_payload.state_open = "OPEN";
discoveryEntry.discovery_payload.state_closed = "CLOSE";
discoveryEntry.discovery_payload.state_stopped = stoppedState;
discoveryEntry.discovery_payload.value_template = `{% if "${featurePropertyWithoutEndpoint(motorState)}" in value_json and value_json["${featurePropertyWithoutEndpoint(motorState)}"] %} {{ value_json["${featurePropertyWithoutEndpoint(motorState)}"] }} {% else %} ${stoppedState} {% endif %}`;
discoveryEntry.discovery_payload.value_template =
`{% if "${motorStateProperty}" in value_json and value_json["${motorStateProperty}"] == "${openingState}" %}` +
`${openingState}` +
`{% elif "${motorStateProperty}" in value_json and value_json["${motorStateProperty}"] == "${closingState}" %}` +
`${closingState}` +
`{% elif "${stateProperty}" in value_json %}` +
`{{ value_json["${stateProperty}"] }}` +
`{% else %}` +
`${stoppedState}` +
`{% endif %}`;
}
}
+14 -2
View File
@@ -1669,12 +1669,14 @@ describe("Extension: HomeAssistant", () => {
position_topic: "zigbee2mqtt/0xa4c138018cf95021/left",
set_position_template: '{ "position_left": {{ position }} }',
set_position_topic: "zigbee2mqtt/0xa4c138018cf95021/left/set",
state_closed: "CLOSE",
state_closing: "DOWN",
state_open: "OPEN",
state_opening: "UP",
state_stopped: "STOP",
state_topic: "zigbee2mqtt/0xa4c138018cf95021/left",
unique_id: "0xa4c138018cf95021_cover_left_zigbee2mqtt",
value_template: '{% if "moving" in value_json and value_json["moving"] %} {{ value_json["moving"] }} {% else %} STOP {% endif %}',
value_template: '{% if "moving" in value_json and value_json["moving"] == "UP" %}UP{% elif "moving" in value_json and value_json["moving"] == "DOWN" %}DOWN{% elif "state" in value_json %}{{ value_json["state"] }}{% else %}STOP{% endif %}',
};
const payload_right = {
availability: [
@@ -1700,14 +1702,24 @@ describe("Extension: HomeAssistant", () => {
position_topic: "zigbee2mqtt/0xa4c138018cf95021/right",
set_position_template: '{ "position_right": {{ position }} }',
set_position_topic: "zigbee2mqtt/0xa4c138018cf95021/right/set",
state_closed: "CLOSE",
state_closing: "DOWN",
state_open: "OPEN",
state_opening: "UP",
state_stopped: "STOP",
state_topic: "zigbee2mqtt/0xa4c138018cf95021/right",
unique_id: "0xa4c138018cf95021_cover_right_zigbee2mqtt",
value_template: '{% if "moving" in value_json and value_json["moving"] %} {{ value_json["moving"] }} {% else %} STOP {% endif %}',
value_template: '{% if "moving" in value_json and value_json["moving"] == "UP" %}UP{% elif "moving" in value_json and value_json["moving"] == "DOWN" %}DOWN{% elif "state" in value_json %}{{ value_json["state"] }}{% else %}STOP{% endif %}',
};
const coverLeftCalls = mockMQTTPublishAsync.mock.calls.filter(
([topic]) => topic === "homeassistant/cover/0xa4c138018cf95021/cover_left/config",
);
for (const [, actualPayload] of coverLeftCalls) {
console.log(JSON.parse(actualPayload));
}
expect(mockMQTTPublishAsync).toHaveBeenCalledWith("homeassistant/cover/0xa4c138018cf95021/cover_left/config", stringify(payload_left), {
retain: true,
qos: 1,