Fix MQTT retained event messages should be discarded (#106425)

pull/105955/head
Jan Bouwhuis 2023-12-27 12:48:53 +01:00 committed by GitHub
parent 25f9c5f34b
commit dae8c0fc38
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 72 additions and 2 deletions

View File

@ -35,7 +35,6 @@ from .mixins import (
MQTT_ENTITY_COMMON_SCHEMA,
MqttEntity,
async_setup_entity_entry_helper,
write_state_on_attr_change,
)
from .models import (
MqttValueTemplate,
@ -43,6 +42,7 @@ from .models import (
ReceiveMessage,
ReceivePayloadType,
)
from .util import get_mqtt_data
_LOGGER = logging.getLogger(__name__)
@ -120,9 +120,15 @@ class MqttEvent(MqttEntity, EventEntity):
@callback
@log_messages(self.hass, self.entity_id)
@write_state_on_attr_change(self, {"state"})
def message_received(msg: ReceiveMessage) -> None:
"""Handle new MQTT messages."""
if msg.retain:
_LOGGER.debug(
"Ignoring event trigger from replayed retained payload '%s' on topic %s",
msg.payload,
msg.topic,
)
return
event_attributes: dict[str, Any] = {}
event_type: str
payload = self._template(msg.payload, PayloadSentinel.DEFAULT)
@ -183,6 +189,8 @@ class MqttEvent(MqttEntity, EventEntity):
payload,
)
return
mqtt_data = get_mqtt_data(self.hass)
mqtt_data.state_write_requests.write_state_request(self)
topics["state_topic"] = {
"topic": self._config[CONF_STATE_TOPIC],

View File

@ -88,6 +88,68 @@ async def test_setting_event_value_via_mqtt_message(
assert state.attributes.get("duration") == "short"
@pytest.mark.freeze_time("2023-08-01 00:00:00+00:00")
@pytest.mark.parametrize("hass_config", [DEFAULT_CONFIG])
async def test_multiple_events_are_all_updating_the_state(
hass: HomeAssistant, mqtt_mock_entry: MqttMockHAClientGenerator
) -> None:
"""Test all events are respected and trigger a state write."""
await mqtt_mock_entry()
with patch(
"homeassistant.components.mqtt.mixins.MqttEntity.async_write_ha_state"
) as mock_async_ha_write_state:
async_fire_mqtt_message(
hass, "test-topic", '{"event_type": "press", "duration": "short" }'
)
assert len(mock_async_ha_write_state.mock_calls) == 1
async_fire_mqtt_message(
hass, "test-topic", '{"event_type": "press", "duration": "short" }'
)
assert len(mock_async_ha_write_state.mock_calls) == 2
@pytest.mark.parametrize("hass_config", [DEFAULT_CONFIG])
async def test_handling_retained_event_payloads(
hass: HomeAssistant, mqtt_mock_entry: MqttMockHAClientGenerator
) -> None:
"""Test if event messages with a retained flag are ignored."""
await mqtt_mock_entry()
with patch(
"homeassistant.components.mqtt.mixins.MqttEntity.async_write_ha_state"
) as mock_async_ha_write_state:
async_fire_mqtt_message(
hass,
"test-topic",
'{"event_type": "press", "duration": "short" }',
retain=True,
)
assert len(mock_async_ha_write_state.mock_calls) == 0
async_fire_mqtt_message(
hass,
"test-topic",
'{"event_type": "press", "duration": "short" }',
retain=False,
)
assert len(mock_async_ha_write_state.mock_calls) == 1
async_fire_mqtt_message(
hass,
"test-topic",
'{"event_type": "press", "duration": "short" }',
retain=True,
)
assert len(mock_async_ha_write_state.mock_calls) == 1
async_fire_mqtt_message(
hass,
"test-topic",
'{"event_type": "press", "duration": "short" }',
retain=False,
)
assert len(mock_async_ha_write_state.mock_calls) == 2
@pytest.mark.freeze_time("2023-08-01 00:00:00+00:00")
@pytest.mark.parametrize("hass_config", [DEFAULT_CONFIG])
@pytest.mark.parametrize(