Update to new Home Assistant MQTT Fan discovery (#7359)

* Update to new Home Assistant MQTT Fan discovery

- Support 3 generic speeds plus presets.

* Customize Home Assistant discovery for 99432

* Revert "Update homeassistant.js"

This reverts commit 87b0a93c7a43244a58741c72cb8dabc58e1dc87e.

* Fix

* fix

* u

* Update homeassistant.js

Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
This commit is contained in:
Colin McCambridge
2021-07-04 20:30:33 +02:00
committed by GitHub
co-authored by Koen Kanters
parent 53ae10e17b
commit 67391615d9
2 changed files with 69 additions and 18 deletions
+59 -10
View File
@@ -321,10 +321,51 @@ class HomeAssistant extends Extension {
const speed = firstExpose.features.find((e) => e.name === 'mode');
if (speed) {
discoveryEntry.discovery_payload.speed_state_topic = true;
discoveryEntry.discovery_payload.speed_command_topic = true;
discoveryEntry.discovery_payload.speed_value_template = '{{ value_json.fan_mode }}';
discoveryEntry.discovery_payload.speeds = speed.values;
// A fan entity in Home Assistant 2021.3 and above may have a speed,
// controlled by a percentage from 1 to 100, and/or non-speed presets.
// The MQTT Fan integration allows the speed percentage to be mapped
// to a narrower range of speeds (e.g. 1-3), and for these speeds to be
// translated to and from MQTT messages via templates.
//
// For the fixed fan modes in ZCL hvacFanCtrl, we model speeds "low",
// "medium", and "high" as three speeds covering the full percentage
// range as done in Home Assistant's zigpy fan integration, plus
// presets "on", "auto" and "smart" to cover the remaining modes in
// ZCL. This supports a generic ZCL HVAC Fan Control fan. "Off" is
// always a valid speed.
let speeds =
['off'].concat(['low', 'medium', 'high'].filter((s) => speed.values.includes(s)));
let presets = ['on', 'auto', 'smart'].filter((s) => speed.values.includes(s));
if (['99432'].includes(definition.model)) {
// The Hampton Bay 99432 fan implements 4 speeds using the ZCL
// hvacFanCtrl values `low`, `medium`, `high`, and `on`, and
// 1 preset called "Comfort Breeze" using the ZCL value `smart`.
// ZCL value `auto` is unused.
speeds = ['off', 'low', 'medium', 'high', 'on'];
presets = ['smart'];
}
const allowed = [...speeds, ...presets];
speed.values.forEach((s) => assert(allowed.includes(s)));
const percentValues = speeds.map((s, i) => `'${s}':${i}`).join(', ');
const percentCommands = speeds.map((s, i) => `${i}:'${s}'`).join(', ');
const presetList = presets.map((s) => `'${s}'`).join(', ');
discoveryEntry.discovery_payload.percentage_state_topic = true;
discoveryEntry.discovery_payload.percentage_command_topic = true;
discoveryEntry.discovery_payload.percentage_value_template =
`{{ {${percentValues}}[value_json.${speed.property}] | default('None') }}`;
discoveryEntry.discovery_payload.percentage_command_template =
`{{ {${percentCommands}}[value] | default('') }}`;
discoveryEntry.discovery_payload.speed_range_min = 1;
discoveryEntry.discovery_payload.speed_range_max = speeds.length - 1;
discoveryEntry.discovery_payload.preset_mode_state_topic = true;
discoveryEntry.discovery_payload.preset_mode_command_topic = true;
discoveryEntry.discovery_payload.preset_mode_value_template =
`{{ value_json.${speed.property} if value_json.${speed.property} in [${presetList}]` +
` else 'None' | default('None') }}`;
discoveryEntry.discovery_payload.preset_modes = presets;
}
} else if (firstExpose.type === 'binary') {
const lookup = {
@@ -811,10 +852,6 @@ class HomeAssistant extends Extension {
payload.temperature_high_state_topic = stateTopic;
}
if (payload.speed_state_topic) {
payload.speed_state_topic = stateTopic;
}
if (payload.temperature_command_topic) {
payload.temperature_command_topic = `${stateTopic}/set/${payload.temperature_command_topic}`;
}
@@ -835,8 +872,20 @@ class HomeAssistant extends Extension {
payload.fan_mode_command_topic = `${stateTopic}/set/fan_mode`;
}
if (payload.speed_command_topic) {
payload.speed_command_topic = `${stateTopic}/set/fan_mode`;
if (payload.percentage_state_topic) {
payload.percentage_state_topic = stateTopic;
}
if (payload.percentage_command_topic) {
payload.percentage_command_topic = `${stateTopic}/set/fan_mode`;
}
if (payload.preset_mode_state_topic) {
payload.preset_mode_state_topic = stateTopic;
}
if (payload.preset_mode_command_topic) {
payload.preset_mode_command_topic = `${stateTopic}/set/fan_mode`;
}
if (payload.action_topic) {
+10 -8
View File
@@ -625,16 +625,18 @@ describe('HomeAssistant extension', () => {
"state_topic":"zigbee2mqtt/fan",
"state_value_template":"{{ value_json.fan_state }}",
"command_topic":"zigbee2mqtt/fan/set/fan_state",
"speed_state_topic":"zigbee2mqtt/fan",
"speed_command_topic":"zigbee2mqtt/fan/set/fan_mode",
"speed_value_template":"{{ value_json.fan_mode }}",
"speeds":[
"low",
"medium",
"high",
"on",
"percentage_state_topic":"zigbee2mqtt/fan",
"percentage_command_topic":"zigbee2mqtt/fan/set/fan_mode",
"percentage_value_template":"{{ {'off':0, 'low':1, 'medium':2, 'high':3, 'on':4}[value_json.fan_mode] | default('None') }}",
"percentage_command_template":"{{ {0:'off', 1:'low', 2:'medium', 3:'high', 4:'on'}[value] | default('') }}",
"preset_mode_state_topic":"zigbee2mqtt/fan",
"preset_mode_command_topic":"zigbee2mqtt/fan/set/fan_mode",
"preset_mode_value_template":"{{ value_json.fan_mode if value_json.fan_mode in ['smart'] else 'None' | default('None') }}",
"preset_modes":[
"smart"
],
"speed_range_min":1,
"speed_range_max":4,
"json_attributes_topic":"zigbee2mqtt/fan",
"name":"fan",
"unique_id":"0x0017880104e45548_fan_zigbee2mqtt",