From ce02cbefc9b4d26438d79fcf66e2e41e6c591cc1 Mon Sep 17 00:00:00 2001 From: Jan Bouwhuis Date: Mon, 25 Sep 2023 18:03:52 +0200 Subject: [PATCH] Avoid redundant calls to async_write_ha_state in mqtt lawn_mower (#100795) Avoid redundant calls to async_write_ha_state --- homeassistant/components/mqtt/lawn_mower.py | 12 ++++--- tests/components/mqtt/test_lawn_mower.py | 38 +++++++++++++++++++++ 2 files changed, 46 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/mqtt/lawn_mower.py b/homeassistant/components/mqtt/lawn_mower.py index fc3996ffbff..42761d224f8 100644 --- a/homeassistant/components/mqtt/lawn_mower.py +++ b/homeassistant/components/mqtt/lawn_mower.py @@ -32,7 +32,12 @@ from .const import ( DEFAULT_RETAIN, ) 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, @@ -40,7 +45,7 @@ from .models import ( ReceiveMessage, ReceivePayloadType, ) -from .util import get_mqtt_data, valid_publish_topic, valid_subscribe_topic +from .util import valid_publish_topic, valid_subscribe_topic _LOGGER = logging.getLogger(__name__) @@ -168,6 +173,7 @@ class MqttLawnMower(MqttEntity, LawnMowerEntity, RestoreEntity): @callback @log_messages(self.hass, self.entity_id) + @write_state_on_attr_change(self, {"_attr_activity"}) def message_received(msg: ReceiveMessage) -> None: """Handle new MQTT messages.""" payload = str(self._value_template(msg.payload)) @@ -180,7 +186,6 @@ class MqttLawnMower(MqttEntity, LawnMowerEntity, RestoreEntity): return if payload.lower() == "none": self._attr_activity = None - get_mqtt_data(self.hass).state_write_requests.write_state_request(self) return try: @@ -193,7 +198,6 @@ class MqttLawnMower(MqttEntity, LawnMowerEntity, RestoreEntity): [option.value for option in LawnMowerActivity], ) return - get_mqtt_data(self.hass).state_write_requests.write_state_request(self) if self._config.get(CONF_ACTIVITY_STATE_TOPIC) is None: # Force into optimistic mode. diff --git a/tests/components/mqtt/test_lawn_mower.py b/tests/components/mqtt/test_lawn_mower.py index b7130cac3bf..85df2caef6c 100644 --- a/tests/components/mqtt/test_lawn_mower.py +++ b/tests/components/mqtt/test_lawn_mower.py @@ -24,6 +24,7 @@ from homeassistant.const import ( from homeassistant.core import HomeAssistant, State from .test_common import ( + help_custom_config, help_test_availability_when_connection_lost, help_test_availability_without_topic, help_test_custom_availability_payload, @@ -47,6 +48,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, @@ -886,3 +888,39 @@ async def test_persistent_state_after_reconfig( # assert the state persistent state = hass.states.get("lawn_mower.garden") assert state.state == "docked" + + +@pytest.mark.parametrize( + "hass_config", + [ + help_custom_config( + lawn_mower.DOMAIN, + DEFAULT_CONFIG, + ( + { + "activity_state_topic": "activity-state-topic", + "availability_topic": "availability-topic", + "json_attributes_topic": "json-attributes-topic", + }, + ), + ) + ], +) +@pytest.mark.parametrize( + ("topic", "payload1", "payload2"), + [ + ("activity-state-topic", "mowing", "paused"), + ("availability-topic", "online", "offline"), + ("json-attributes-topic", '{"attr1": "val1"}', '{"attr1": "val2"}'), + ], +) +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)