From 4881bc04d802b1d130dcbc3cba55c08e3cc298ad Mon Sep 17 00:00:00 2001
From: Dmitry Krasnoukhov <dmitry@krasnoukhov.com>
Date: Tue, 26 Nov 2019 06:53:37 +0200
Subject: [PATCH] Allow to change MQTT climate hold mode (#28988)

---
 homeassistant/components/mqtt/climate.py | 12 +++++++-----
 tests/components/mqtt/test_climate.py    | 20 ++++++++++++++++++++
 2 files changed, 27 insertions(+), 5 deletions(-)

diff --git a/homeassistant/components/mqtt/climate.py b/homeassistant/components/mqtt/climate.py
index 4b163c523fa..9b46057a414 100644
--- a/homeassistant/components/mqtt/climate.py
+++ b/homeassistant/components/mqtt/climate.py
@@ -756,12 +756,14 @@ class MqttClimate(
         if self._away:
             optimistic_update = optimistic_update or self._set_away_mode(False)
         elif preset_mode == PRESET_AWAY:
+            if self._hold:
+                self._set_hold_mode(None)
             optimistic_update = optimistic_update or self._set_away_mode(True)
-
-        if self._hold:
-            optimistic_update = optimistic_update or self._set_hold_mode(None)
-        elif preset_mode not in (None, PRESET_AWAY):
-            optimistic_update = optimistic_update or self._set_hold_mode(preset_mode)
+        else:
+            hold_mode = preset_mode
+            if preset_mode == PRESET_NONE:
+                hold_mode = None
+            optimistic_update = optimistic_update or self._set_hold_mode(hold_mode)
 
         if optimistic_update:
             self.async_write_ha_state()
diff --git a/tests/components/mqtt/test_climate.py b/tests/components/mqtt/test_climate.py
index 3f4fc657186..648448a6494 100644
--- a/tests/components/mqtt/test_climate.py
+++ b/tests/components/mqtt/test_climate.py
@@ -23,6 +23,7 @@ from homeassistant.components.climate.const import (
     HVAC_MODE_FAN_ONLY,
     SUPPORT_TARGET_TEMPERATURE_RANGE,
     PRESET_NONE,
+    PRESET_ECO,
 )
 from homeassistant.components.mqtt.discovery import async_start
 from homeassistant.const import STATE_OFF, STATE_UNAVAILABLE
@@ -446,6 +447,19 @@ async def test_set_away_mode(hass, mqtt_mock):
     state = hass.states.get(ENTITY_CLIMATE)
     assert state.attributes.get("preset_mode") is None
 
+    await common.async_set_preset_mode(hass, "hold-on", ENTITY_CLIMATE)
+    mqtt_mock.async_publish.reset_mock()
+
+    await common.async_set_preset_mode(hass, "away", ENTITY_CLIMATE)
+    mqtt_mock.async_publish.assert_has_calls(
+        [
+            unittest.mock.call("hold-topic", "off", 0, False),
+            unittest.mock.call("away-mode-topic", "AN", 0, False),
+        ]
+    )
+    state = hass.states.get(ENTITY_CLIMATE)
+    assert state.attributes.get("preset_mode") == "away"
+
 
 async def test_set_hvac_action(hass, mqtt_mock):
     """Test setting of the HVAC action."""
@@ -495,6 +509,12 @@ async def test_set_hold(hass, mqtt_mock):
     state = hass.states.get(ENTITY_CLIMATE)
     assert state.attributes.get("preset_mode") == "hold-on"
 
+    await common.async_set_preset_mode(hass, PRESET_ECO, ENTITY_CLIMATE)
+    mqtt_mock.async_publish.assert_called_once_with("hold-topic", "eco", 0, False)
+    mqtt_mock.async_publish.reset_mock()
+    state = hass.states.get(ENTITY_CLIMATE)
+    assert state.attributes.get("preset_mode") == PRESET_ECO
+
     await common.async_set_preset_mode(hass, PRESET_NONE, ENTITY_CLIMATE)
     mqtt_mock.async_publish.assert_called_once_with("hold-topic", "off", 0, False)
     state = hass.states.get(ENTITY_CLIMATE)