diff --git a/homeassistant/components/mqtt/lock.py b/homeassistant/components/mqtt/lock.py index b565e8a4b57..9a0ce2077f3 100644 --- a/homeassistant/components/mqtt/lock.py +++ b/homeassistant/components/mqtt/lock.py @@ -28,6 +28,7 @@ from .const import ( CONF_COMMAND_TEMPLATE, CONF_COMMAND_TOPIC, CONF_ENCODING, + CONF_PAYLOAD_RESET, CONF_QOS, CONF_RETAIN, CONF_STATE_TOPIC, @@ -63,6 +64,7 @@ DEFAULT_NAME = "MQTT Lock" DEFAULT_PAYLOAD_LOCK = "LOCK" DEFAULT_PAYLOAD_UNLOCK = "UNLOCK" DEFAULT_PAYLOAD_OPEN = "OPEN" +DEFAULT_PAYLOAD_RESET = "None" DEFAULT_STATE_LOCKED = "LOCKED" DEFAULT_STATE_LOCKING = "LOCKING" DEFAULT_STATE_UNLOCKED = "UNLOCKED" @@ -84,6 +86,7 @@ PLATFORM_SCHEMA_MODERN = MQTT_RW_SCHEMA.extend( vol.Optional(CONF_PAYLOAD_LOCK, default=DEFAULT_PAYLOAD_LOCK): cv.string, vol.Optional(CONF_PAYLOAD_UNLOCK, default=DEFAULT_PAYLOAD_UNLOCK): cv.string, vol.Optional(CONF_PAYLOAD_OPEN): cv.string, + vol.Optional(CONF_PAYLOAD_RESET, default=DEFAULT_PAYLOAD_RESET): cv.string, 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, @@ -197,8 +200,12 @@ class MqttLock(MqttEntity, LockEntity): ) def message_received(msg: ReceiveMessage) -> None: """Handle new lock state messages.""" - payload = self._value_template(msg.payload) - if payload in self._valid_states: + if (payload := self._value_template(msg.payload)) == self._config[ + CONF_PAYLOAD_RESET + ]: + # Reset the state to `unknown` + self._attr_is_locked = None + 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_unlocking = payload == self._config[CONF_STATE_UNLOCKING] diff --git a/tests/components/mqtt/test_lock.py b/tests/components/mqtt/test_lock.py index 0045e003804..e128590c907 100644 --- a/tests/components/mqtt/test_lock.py +++ b/tests/components/mqtt/test_lock.py @@ -126,6 +126,7 @@ async def test_controlling_state_via_topic( (CONFIG_WITH_STATES, "closing", STATE_LOCKING), (CONFIG_WITH_STATES, "open", STATE_UNLOCKED), (CONFIG_WITH_STATES, "opening", STATE_UNLOCKING), + (CONFIG_WITH_STATES, "None", STATE_UNKNOWN), ], ) async def test_controlling_non_default_state_via_topic( @@ -186,6 +187,15 @@ async def test_controlling_non_default_state_via_topic( '{"val":"open"}', STATE_UNLOCKED, ), + ( + help_custom_config( + lock.DOMAIN, + CONFIG_WITH_STATES, + ({"value_template": "{{ value_json.val }}"},), + ), + '{"val":null}', + STATE_UNKNOWN, + ), ], ) async def test_controlling_state_via_topic_and_json_message(