Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ensure all mqtt messages report state to core #140001

Draft
wants to merge 4 commits into
base: dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 1 addition & 6 deletions homeassistant/components/mqtt/entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -1454,11 +1454,6 @@ def _message_callback(
msg: ReceiveMessage,
) -> None:
"""Process the message callback."""
if attributes is not None:
attrs_snapshot: tuple[tuple[str, Any | UndefinedType], ...] = tuple(
(attribute, getattr(self, attribute, UNDEFINED))
for attribute in attributes
)
mqtt_data = self.hass.data[DATA_MQTT]
messages = mqtt_data.debug_info_entities[self.entity_id]["subscriptions"][
msg.subscribed_topic
Expand All @@ -1472,7 +1467,7 @@ def _message_callback(
_LOGGER.warning(exc)
return

if attributes is not None and self._attrs_have_changed(attrs_snapshot):
if attributes is not None:
mqtt_data.state_write_requests.write_state_request(self)

def add_subscription(
Expand Down
41 changes: 0 additions & 41 deletions tests/components/mqtt/test_alarm_control_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@
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,
Expand Down Expand Up @@ -1293,46 +1292,6 @@ async def test_entity_icon_and_entity_picture(
)


@pytest.mark.parametrize(
"hass_config",
[
help_custom_config(
alarm_control_panel.DOMAIN,
DEFAULT_CONFIG,
(
{
"availability_topic": "availability-topic",
"json_attributes_topic": "json-attributes-topic",
"state_topic": "test-topic",
},
),
)
],
)
@pytest.mark.parametrize(
("topic", "payload1", "payload2"),
[
(
"test-topic",
AlarmControlPanelState.DISARMED,
AlarmControlPanelState.ARMED_HOME,
),
("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)


@pytest.mark.parametrize(
"hass_config",
[
Expand Down
36 changes: 0 additions & 36 deletions tests/components/mqtt/test_binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@
help_test_reloadable,
help_test_setting_attribute_via_mqtt_json_message,
help_test_setting_attribute_with_template,
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,
Expand Down Expand Up @@ -1207,41 +1206,6 @@ async def test_entity_icon_and_entity_picture(
)


@pytest.mark.parametrize(
"hass_config",
[
help_custom_config(
binary_sensor.DOMAIN,
DEFAULT_CONFIG,
(
{
"availability_topic": "availability-topic",
"json_attributes_topic": "json-attributes-topic",
},
),
)
],
)
@pytest.mark.parametrize(
("topic", "payload1", "payload2"),
[
("test-topic", "ON", "OFF"),
("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)


@pytest.mark.parametrize(
"hass_config",
[
Expand Down
60 changes: 0 additions & 60 deletions tests/components/mqtt/test_climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@
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,
Expand Down Expand Up @@ -2451,65 +2450,6 @@ async def test_unload_entry(
)


@pytest.mark.parametrize(
"hass_config",
[
help_custom_config(
climate.DOMAIN,
DEFAULT_CONFIG,
(
{
"availability_topic": "availability-topic",
"json_attributes_topic": "json-attributes-topic",
"action_topic": "action-topic",
"fan_mode_state_topic": "fan-mode-state-topic",
"mode_state_topic": "mode-state-topic",
"current_humidity_topic": "current-humidity-topic",
"current_temperature_topic": "current-temperature-topic",
"preset_mode_state_topic": "preset-mode-state-topic",
"preset_modes": ["eco", "away"],
"swing_horizontal_mode_state_topic": "swing-horizontal-mode-state-topic",
"swing_mode_state_topic": "swing-mode-state-topic",
"target_humidity_state_topic": "target-humidity-state-topic",
"temperature_high_state_topic": "temperature-high-state-topic",
"temperature_low_state_topic": "temperature-low-state-topic",
"temperature_state_topic": "temperature-state-topic",
},
),
)
],
)
@pytest.mark.parametrize(
("topic", "payload1", "payload2"),
[
("availability-topic", "online", "offline"),
("json-attributes-topic", '{"attr1": "val1"}', '{"attr1": "val2"}'),
("action-topic", "cooling", "heating"),
("fan-mode-state-topic", "low", "medium"),
("mode-state-topic", "cool", "heat"),
("current-humidity-topic", "45", "46"),
("current-temperature-topic", "18.0", "18.1"),
("preset-mode-state-topic", "eco", "away"),
("swing-horizontal-mode-state-topic", "on", "off"),
("swing-mode-state-topic", "on", "off"),
("target-humidity-state-topic", "45", "50"),
("temperature-state-topic", "18", "19"),
("temperature-low-state-topic", "18", "19"),
("temperature-high-state-topic", "18", "19"),
],
)
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)


@pytest.mark.parametrize(
"hass_config",
[
Expand Down
25 changes: 0 additions & 25 deletions tests/components/mqtt/test_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -2003,28 +2003,3 @@ async def help_test_discovery_setup(
await hass.async_block_till_done()
state = hass.states.get(f"{domain}.{name}")
assert state and state.state is not None


async def help_test_skipped_async_ha_write_state(
hass: HomeAssistant, topic: str, payload1: str, payload2: str
) -> None:
"""Test entity.async_ha_write_state is only called on changes."""
with patch(
"homeassistant.components.mqtt.entity.MqttEntity.async_write_ha_state"
) as mock_async_ha_write_state:
assert len(mock_async_ha_write_state.mock_calls) == 0
async_fire_mqtt_message(hass, topic, payload1)
await hass.async_block_till_done()
assert len(mock_async_ha_write_state.mock_calls) == 1

async_fire_mqtt_message(hass, topic, payload1)
await hass.async_block_till_done()
assert len(mock_async_ha_write_state.mock_calls) == 1

async_fire_mqtt_message(hass, topic, payload2)
await hass.async_block_till_done()
assert len(mock_async_ha_write_state.mock_calls) == 2

async_fire_mqtt_message(hass, topic, payload2)
await hass.async_block_till_done()
assert len(mock_async_ha_write_state.mock_calls) == 2
41 changes: 0 additions & 41 deletions tests/components/mqtt/test_cover.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@
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,
Expand Down Expand Up @@ -3471,46 +3470,6 @@ async def test_unload_entry(
)


@pytest.mark.parametrize(
"hass_config",
[
help_custom_config(
cover.DOMAIN,
DEFAULT_CONFIG,
(
{
"availability_topic": "availability-topic",
"json_attributes_topic": "json-attributes-topic",
"state_topic": "test-topic",
"position_topic": "position-topic",
"tilt_status_topic": "tilt-status-topic",
},
),
)
],
)
@pytest.mark.parametrize(
("topic", "payload1", "payload2"),
[
("test-topic", "open", "closed"),
("availability-topic", "online", "offline"),
("json-attributes-topic", '{"attr1": "val1"}', '{"attr1": "val2"}'),
("position-topic", "50", "100"),
("tilt-status-topic", "50", "100"),
],
)
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)


VALUE_TEMPLATES = {
CONF_VALUE_TEMPLATE: CONF_STATE_TOPIC,
CONF_GET_POSITION_TEMPLATE: CONF_GET_POSITION_TOPIC,
Expand Down
36 changes: 0 additions & 36 deletions tests/components/mqtt/test_device_tracker.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
help_custom_config,
help_test_reloadable,
help_test_setting_blocked_attribute_via_mqtt_json_message,
help_test_skipped_async_ha_write_state,
)

from tests.common import async_fire_mqtt_message
Expand Down Expand Up @@ -617,41 +616,6 @@ async def test_reloadable(
await help_test_reloadable(hass, mqtt_client_mock, domain, config)


@pytest.mark.parametrize(
"hass_config",
[
help_custom_config(
device_tracker.DOMAIN,
DEFAULT_CONFIG,
(
{
"availability_topic": "availability-topic",
"json_attributes_topic": "json-attributes-topic",
},
),
)
],
)
@pytest.mark.parametrize(
("topic", "payload1", "payload2"),
[
("test-topic", "home", "work"),
("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)


@pytest.mark.parametrize(
"hass_config",
[
Expand Down
35 changes: 0 additions & 35 deletions tests/components/mqtt/test_event.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@
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,
Expand Down Expand Up @@ -718,40 +717,6 @@ async def test_entity_icon_and_entity_picture(
)


@pytest.mark.parametrize(
"hass_config",
[
help_custom_config(
event.DOMAIN,
DEFAULT_CONFIG,
(
{
"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"}'),
],
)
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)


@pytest.mark.freeze_time("2023-09-01 00:00:00+00:00")
@pytest.mark.parametrize("hass_config", [DEFAULT_CONFIG])
async def test_skipped_async_ha_write_state2(
Expand Down
Loading
Loading