diff --git a/homeassistant/components/mqtt/lock.py b/homeassistant/components/mqtt/lock.py index 79e02be9d4f..00f61b5e224 100644 --- a/homeassistant/components/mqtt/lock.py +++ b/homeassistant/components/mqtt/lock.py @@ -31,6 +31,8 @@ from .const import ( CONF_PAYLOAD_RESET, CONF_QOS, CONF_RETAIN, + CONF_STATE_OPEN, + CONF_STATE_OPENING, CONF_STATE_TOPIC, ) from .debug_info import log_messages @@ -56,6 +58,7 @@ CONF_PAYLOAD_OPEN = "payload_open" CONF_STATE_LOCKED = "state_locked" CONF_STATE_LOCKING = "state_locking" + CONF_STATE_UNLOCKED = "state_unlocked" CONF_STATE_UNLOCKING = "state_unlocking" CONF_STATE_JAMMED = "state_jammed" @@ -67,6 +70,8 @@ DEFAULT_PAYLOAD_OPEN = "OPEN" DEFAULT_PAYLOAD_RESET = "None" DEFAULT_STATE_LOCKED = "LOCKED" DEFAULT_STATE_LOCKING = "LOCKING" +DEFAULT_STATE_OPEN = "OPEN" +DEFAULT_STATE_OPENING = "OPENING" DEFAULT_STATE_UNLOCKED = "UNLOCKED" DEFAULT_STATE_UNLOCKING = "UNLOCKING" DEFAULT_STATE_JAMMED = "JAMMED" @@ -90,6 +95,8 @@ PLATFORM_SCHEMA_MODERN = MQTT_RW_SCHEMA.extend( vol.Optional(CONF_STATE_JAMMED, default=DEFAULT_STATE_JAMMED): cv.string, vol.Optional(CONF_STATE_LOCKED, default=DEFAULT_STATE_LOCKED): cv.string, vol.Optional(CONF_STATE_LOCKING, default=DEFAULT_STATE_LOCKING): cv.string, + vol.Optional(CONF_STATE_OPEN, default=DEFAULT_STATE_OPEN): cv.string, + vol.Optional(CONF_STATE_OPENING, default=DEFAULT_STATE_OPENING): cv.string, vol.Optional(CONF_STATE_UNLOCKED, default=DEFAULT_STATE_UNLOCKED): cv.string, vol.Optional(CONF_STATE_UNLOCKING, default=DEFAULT_STATE_UNLOCKING): cv.string, vol.Optional(CONF_VALUE_TEMPLATE): cv.template, @@ -102,6 +109,8 @@ STATE_CONFIG_KEYS = [ CONF_STATE_JAMMED, CONF_STATE_LOCKED, CONF_STATE_LOCKING, + CONF_STATE_OPEN, + CONF_STATE_OPENING, CONF_STATE_UNLOCKED, CONF_STATE_UNLOCKING, ] @@ -189,6 +198,8 @@ class MqttLock(MqttEntity, LockEntity): "_attr_is_jammed", "_attr_is_locked", "_attr_is_locking", + "_attr_is_open", + "_attr_is_opening", "_attr_is_unlocking", }, ) @@ -202,6 +213,8 @@ class MqttLock(MqttEntity, LockEntity): elif payload in self._valid_states: self._attr_is_locked = payload == self._config[CONF_STATE_LOCKED] self._attr_is_locking = payload == self._config[CONF_STATE_LOCKING] + self._attr_is_open = payload == self._config[CONF_STATE_OPEN] + self._attr_is_opening = payload == self._config[CONF_STATE_OPENING] self._attr_is_unlocking = payload == self._config[CONF_STATE_UNLOCKING] self._attr_is_jammed = payload == self._config[CONF_STATE_JAMMED] @@ -286,5 +299,5 @@ class MqttLock(MqttEntity, LockEntity): ) if self._optimistic: # Optimistically assume that the lock unlocks when opened. - self._attr_is_locked = False + self._attr_is_open = True self.async_write_ha_state() diff --git a/tests/components/mqtt/test_lock.py b/tests/components/mqtt/test_lock.py index a52d1ab42f4..4d76b44bb66 100644 --- a/tests/components/mqtt/test_lock.py +++ b/tests/components/mqtt/test_lock.py @@ -13,6 +13,8 @@ from homeassistant.components.lock import ( STATE_JAMMED, STATE_LOCKED, STATE_LOCKING, + STATE_OPEN, + STATE_OPENING, STATE_UNLOCKED, STATE_UNLOCKING, LockEntityFeature, @@ -75,8 +77,10 @@ CONFIG_WITH_STATES = { "payload_unlock": "UNLOCK", "state_locked": "closed", "state_locking": "closing", - "state_unlocked": "open", - "state_unlocking": "opening", + "state_open": "open", + "state_opening": "opening", + "state_unlocked": "unlocked", + "state_unlocking": "unlocking", } } } @@ -87,8 +91,10 @@ CONFIG_WITH_STATES = { [ (CONFIG_WITH_STATES, "closed", STATE_LOCKED), (CONFIG_WITH_STATES, "closing", STATE_LOCKING), - (CONFIG_WITH_STATES, "open", STATE_UNLOCKED), - (CONFIG_WITH_STATES, "opening", STATE_UNLOCKING), + (CONFIG_WITH_STATES, "open", STATE_OPEN), + (CONFIG_WITH_STATES, "opening", STATE_OPENING), + (CONFIG_WITH_STATES, "unlocked", STATE_UNLOCKED), + (CONFIG_WITH_STATES, "unlocking", STATE_UNLOCKING), ], ) async def test_controlling_state_via_topic( @@ -117,8 +123,10 @@ async def test_controlling_state_via_topic( [ (CONFIG_WITH_STATES, "closed", STATE_LOCKED), (CONFIG_WITH_STATES, "closing", STATE_LOCKING), - (CONFIG_WITH_STATES, "open", STATE_UNLOCKED), - (CONFIG_WITH_STATES, "opening", STATE_UNLOCKING), + (CONFIG_WITH_STATES, "open", STATE_OPEN), + (CONFIG_WITH_STATES, "opening", STATE_OPENING), + (CONFIG_WITH_STATES, "unlocked", STATE_UNLOCKED), + (CONFIG_WITH_STATES, "unlocking", STATE_UNLOCKING), (CONFIG_WITH_STATES, "None", STATE_UNKNOWN), ], ) @@ -168,7 +176,7 @@ async def test_controlling_non_default_state_via_topic( CONFIG_WITH_STATES, ({"value_template": "{{ value_json.val }}"},), ), - '{"val":"opening"}', + '{"val":"unlocking"}', STATE_UNLOCKING, ), ( @@ -178,6 +186,24 @@ async def test_controlling_non_default_state_via_topic( ({"value_template": "{{ value_json.val }}"},), ), '{"val":"open"}', + STATE_OPEN, + ), + ( + help_custom_config( + lock.DOMAIN, + CONFIG_WITH_STATES, + ({"value_template": "{{ value_json.val }}"},), + ), + '{"val":"opening"}', + STATE_OPENING, + ), + ( + help_custom_config( + lock.DOMAIN, + CONFIG_WITH_STATES, + ({"value_template": "{{ value_json.val }}"},), + ), + '{"val":"unlocked"}', STATE_UNLOCKED, ), ( @@ -237,7 +263,7 @@ async def test_controlling_state_via_topic_and_json_message( ({"value_template": "{{ value_json.val }}"},), ), '{"val":"open"}', - STATE_UNLOCKED, + STATE_OPEN, ), ( help_custom_config( @@ -246,6 +272,24 @@ async def test_controlling_state_via_topic_and_json_message( ({"value_template": "{{ value_json.val }}"},), ), '{"val":"opening"}', + STATE_OPENING, + ), + ( + help_custom_config( + lock.DOMAIN, + CONFIG_WITH_STATES, + ({"value_template": "{{ value_json.val }}"},), + ), + '{"val":"unlocked"}', + STATE_UNLOCKED, + ), + ( + help_custom_config( + lock.DOMAIN, + CONFIG_WITH_STATES, + ({"value_template": "{{ value_json.val }}"},), + ), + '{"val":"unlocking"}', STATE_UNLOCKING, ), ], @@ -483,7 +527,7 @@ async def test_sending_mqtt_commands_support_open_and_optimistic( mqtt_mock.async_publish.assert_called_once_with("command-topic", "OPEN", 0, False) mqtt_mock.async_publish.reset_mock() state = hass.states.get("lock.test") - assert state.state is STATE_UNLOCKED + assert state.state is STATE_OPEN assert state.attributes.get(ATTR_ASSUMED_STATE) @@ -545,7 +589,7 @@ async def test_sending_mqtt_commands_support_open_and_explicit_optimistic( mqtt_mock.async_publish.assert_called_once_with("command-topic", "OPEN", 0, False) mqtt_mock.async_publish.reset_mock() state = hass.states.get("lock.test") - assert state.state is STATE_UNLOCKED + assert state.state is STATE_OPEN assert state.attributes.get(ATTR_ASSUMED_STATE)