diff --git a/homeassistant/components/mqtt/cover.py b/homeassistant/components/mqtt/cover.py index fd3e36c04e1..d920d12662f 100644 --- a/homeassistant/components/mqtt/cover.py +++ b/homeassistant/components/mqtt/cover.py @@ -245,11 +245,45 @@ class MqttCover(MqttEntity, CoverEntity): return PLATFORM_SCHEMA def _setup_from_config(self, config): - self._optimistic = config[CONF_OPTIMISTIC] or ( - config.get(CONF_STATE_TOPIC) is None + no_position = ( + config.get(CONF_SET_POSITION_TOPIC) is None and config.get(CONF_GET_POSITION_TOPIC) is None ) - self._tilt_optimistic = config[CONF_TILT_STATE_OPTIMISTIC] + no_state = ( + config.get(CONF_COMMAND_TOPIC) is None + and config.get(CONF_STATE_TOPIC) is None + ) + no_tilt = ( + config.get(CONF_TILT_COMMAND_TOPIC) is None + and config.get(CONF_TILT_STATUS_TOPIC) is None + ) + optimistic_position = ( + config.get(CONF_SET_POSITION_TOPIC) is not None + and config.get(CONF_GET_POSITION_TOPIC) is None + ) + optimistic_state = ( + config.get(CONF_COMMAND_TOPIC) is not None + and config.get(CONF_STATE_TOPIC) is None + ) + optimistic_tilt = ( + config.get(CONF_TILT_COMMAND_TOPIC) is not None + and config.get(CONF_TILT_STATUS_TOPIC) is None + ) + + if config[CONF_OPTIMISTIC] or ( + (no_position or optimistic_position) + and (no_state or optimistic_state) + and (no_tilt or optimistic_tilt) + ): + # Force into optimistic mode. + self._optimistic = True + + if ( + config[CONF_TILT_STATE_OPTIMISTIC] + or config.get(CONF_TILT_STATUS_TOPIC) is None + ): + # Force into optimistic tilt mode. + self._tilt_optimistic = True value_template = self._config.get(CONF_VALUE_TEMPLATE) if value_template is not None: @@ -418,17 +452,7 @@ class MqttCover(MqttEntity, CoverEntity): "qos": self._config[CONF_QOS], } - if ( - self._config.get(CONF_GET_POSITION_TOPIC) is None - and self._config.get(CONF_STATE_TOPIC) is None - ): - # Force into optimistic mode. - self._optimistic = True - - if self._config.get(CONF_TILT_STATUS_TOPIC) is None: - # Force into optimistic tilt mode. - self._tilt_optimistic = True - else: + if self._config.get(CONF_TILT_STATUS_TOPIC) is not None: self._tilt_value = STATE_UNKNOWN topics["tilt_status_topic"] = { "topic": self._config.get(CONF_TILT_STATUS_TOPIC), diff --git a/tests/components/mqtt/test_cover.py b/tests/components/mqtt/test_cover.py index 7d763895428..0ee2557fbd6 100644 --- a/tests/components/mqtt/test_cover.py +++ b/tests/components/mqtt/test_cover.py @@ -393,6 +393,34 @@ async def test_position_via_template_and_entity_id(hass, mqtt_mock): assert current_cover_position == 20 +@pytest.mark.parametrize( + "config, assumed_state", + [ + ({"command_topic": "abc"}, True), + ({"command_topic": "abc", "state_topic": "abc"}, False), + # ({"set_position_topic": "abc"}, True), - not a valid configuration + ({"set_position_topic": "abc", "position_topic": "abc"}, False), + ({"tilt_command_topic": "abc"}, True), + ({"tilt_command_topic": "abc", "tilt_status_topic": "abc"}, False), + ], +) +async def test_optimistic_flag(hass, mqtt_mock, config, assumed_state): + """Test assumed_state is set correctly.""" + assert await async_setup_component( + hass, + cover.DOMAIN, + {cover.DOMAIN: {**config, "platform": "mqtt", "name": "test", "qos": 0}}, + ) + await hass.async_block_till_done() + + state = hass.states.get("cover.test") + assert state.state == STATE_UNKNOWN + if assumed_state: + assert ATTR_ASSUMED_STATE in state.attributes + else: + assert ATTR_ASSUMED_STATE not in state.attributes + + async def test_optimistic_state_change(hass, mqtt_mock): """Test changing state optimistically.""" assert await async_setup_component(