From 98cc2e8098113b39848f0d3d994beaebc187bafb Mon Sep 17 00:00:00 2001 From: Jan Bouwhuis Date: Mon, 25 Sep 2023 18:04:33 +0200 Subject: [PATCH] Avoid redundant calls to async_write_ha_state in mqtt lock (#100802) Avoid redundant calls to async_write_ha_state --- homeassistant/components/mqtt/lock.py | 19 +++++++++++--- tests/components/mqtt/test_lock.py | 38 +++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/mqtt/lock.py b/homeassistant/components/mqtt/lock.py index d2e67ba40da..ebc4eced9c2 100644 --- a/homeassistant/components/mqtt/lock.py +++ b/homeassistant/components/mqtt/lock.py @@ -33,7 +33,12 @@ from .const import ( CONF_STATE_TOPIC, ) from .debug_info import log_messages -from .mixins import MQTT_ENTITY_COMMON_SCHEMA, MqttEntity, async_setup_entry_helper +from .mixins import ( + MQTT_ENTITY_COMMON_SCHEMA, + MqttEntity, + async_setup_entry_helper, + write_state_on_attr_change, +) from .models import ( MqttCommandTemplate, MqttValueTemplate, @@ -41,7 +46,6 @@ from .models import ( ReceiveMessage, ReceivePayloadType, ) -from .util import get_mqtt_data CONF_CODE_FORMAT = "code_format" @@ -190,6 +194,15 @@ class MqttLock(MqttEntity, LockEntity): @callback @log_messages(self.hass, self.entity_id) + @write_state_on_attr_change( + self, + { + "_attr_is_jammed", + "_attr_is_locked", + "_attr_is_locking", + "_attr_is_unlocking", + }, + ) def message_received(msg: ReceiveMessage) -> None: """Handle new lock state messages.""" payload = self._value_template(msg.payload) @@ -199,8 +212,6 @@ class MqttLock(MqttEntity, LockEntity): self._attr_is_unlocking = payload == self._config[CONF_STATE_UNLOCKING] self._attr_is_jammed = payload == self._config[CONF_STATE_JAMMED] - get_mqtt_data(self.hass).state_write_requests.write_state_request(self) - if self._config.get(CONF_STATE_TOPIC) is None: # Force into optimistic mode. self._optimistic = True diff --git a/tests/components/mqtt/test_lock.py b/tests/components/mqtt/test_lock.py index bf7e1529a4e..f9a33c211ee 100644 --- a/tests/components/mqtt/test_lock.py +++ b/tests/components/mqtt/test_lock.py @@ -50,6 +50,7 @@ from .test_common import ( help_test_setting_attribute_via_mqtt_json_message, help_test_setting_attribute_with_template, help_test_setting_blocked_attribute_via_mqtt_json_message, + help_test_skipped_async_ha_write_state, help_test_unique_id, help_test_unload_config_entry_with_platform, help_test_update_with_json_attrs_bad_json, @@ -1030,3 +1031,40 @@ async def test_unload_entry( await help_test_unload_config_entry_with_platform( hass, mqtt_mock_entry, domain, config ) + + +@pytest.mark.parametrize( + "hass_config", + [ + help_custom_config( + lock.DOMAIN, + CONFIG_WITH_STATES, + ( + { + "availability_topic": "availability-topic", + "json_attributes_topic": "json-attributes-topic", + }, + ), + ) + ], +) +@pytest.mark.parametrize( + ("topic", "payload1", "payload2"), + [ + ("availability-topic", "online", "offline"), + ("json-attributes-topic", '{"attr1": "val1"}', '{"attr1": "val2"}'), + ("state-topic", "closed", "open"), + ("state-topic", "closed", "opening"), + ("state-topic", "open", "closing"), + ], +) +async def test_skipped_async_ha_write_state( + hass: HomeAssistant, + mqtt_mock_entry: MqttMockHAClientGenerator, + topic: str, + payload1: str, + payload2: str, +) -> None: + """Test a write state command is only called when there is change.""" + await mqtt_mock_entry() + await help_test_skipped_async_ha_write_state(hass, topic, payload1, payload2)