From f95c0bb048f75db0afff18277238ad3d9363c485 Mon Sep 17 00:00:00 2001 From: Artem Draft Date: Wed, 23 Mar 2022 19:19:06 +0300 Subject: [PATCH] Handle cover `motor_state` in HA (#11926) * Handle cover motor_state in HA * lint --- lib/extension/homeassistant.ts | 44 +++++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/lib/extension/homeassistant.ts b/lib/extension/homeassistant.ts index 1f11e4eb8..f2183d0b8 100644 --- a/lib/extension/homeassistant.ts +++ b/lib/extension/homeassistant.ts @@ -380,7 +380,8 @@ export default class HomeAssistant extends Extension { } else if (firstExpose.type === 'cover') { const position = exposes.find((expose) => expose.features.find((e) => e.name === 'position')); const tilt = exposes.find((expose) => expose.features.find((e) => e.name === 'tilt')); - const running = definitionExposes?.find((e) => e.type === 'binary' && e.name === 'running'); + const motorState = definitionExposes?.find((e) => e.type === 'enum' && e.name === 'motor_state' && + e.access === ACCESS_STATE); const discoveryEntry: DiscoveryEntry = { type: 'cover', @@ -397,13 +398,44 @@ export default class HomeAssistant extends Extension { // - https://github.com/Koenkk/zigbee-herdsman-converters/pull/2663 if (!tilt || (tilt && position)) { discoveryEntry.discovery_payload.command_topic = true; - discoveryEntry.discovery_payload.state_topic = !!running || !position; + discoveryEntry.discovery_payload.state_topic = !position; discoveryEntry.discovery_payload.command_topic_prefix = endpoint; - if (running) { - discoveryEntry.discovery_payload.value_template = `{% if not value_json.running %} ` + - `stopped {% else %} {% if value_json.position > 0 %} closing {% else %} ` + - `opening {% endif %} {% endif %}`; + // For curtains that have `motor_state` lookup a possible state names and make this + // available for discovery. If the curtains only support the `running` value, + // then we use it anyway. The movement direction is calculated (assumed) in this case. + if (motorState) { + const openingLookup = ['opening', 'open', 'forward', 'up', 'rising']; + const closingLookup = ['closing', 'close', 'backward', 'back', 'reverse', 'down', 'declining']; + const stoppedLookup = ['stopped', 'stop', 'pause', 'paused']; + + const openingState = motorState.values.find((s) => openingLookup.includes(s.toLowerCase())); + const closingState = motorState.values.find((s) => closingLookup.includes(s.toLowerCase())); + const stoppedState = motorState.values.find((s) => stoppedLookup.includes(s.toLowerCase())); + + if (openingState) { + discoveryEntry.discovery_payload.state_opening = openingState; + } + if (closingState) { + discoveryEntry.discovery_payload.state_closing = closingState; + } + if (stoppedState) { + discoveryEntry.discovery_payload.state_stopped = stoppedState; + } + + if (openingState || closingState || stoppedState) { + discoveryEntry.discovery_payload.state_topic = true; + discoveryEntry.discovery_payload.value_template = `{{ value_json.motor_state }}`; + } + } else { + const running = definitionExposes?.find((e) => e.type === 'binary' && e.name === 'running'); + + if (running) { + discoveryEntry.discovery_payload.state_topic = true; + discoveryEntry.discovery_payload.value_template = `{% if not value_json.running %} ` + + `stopped {% else %} {% if value_json.position > 0 %} closing {% else %} ` + + `opening {% endif %} {% endif %}`; + } } }