Fix mqtt not publishing null payload payload to remove discovery (#118261)

This commit is contained in:
Jan Bouwhuis 2024-05-28 00:53:22 +02:00 committed by GitHub
parent 6067ea2454
commit bfc3194661
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 47 additions and 27 deletions

View File

@ -148,7 +148,7 @@ async def async_publish(
)
mqtt_data = hass.data[DATA_MQTT]
outgoing_payload = payload
if not isinstance(payload, bytes):
if not isinstance(payload, bytes) and payload is not None:
if not encoding:
_LOGGER.error(
(

View File

@ -647,7 +647,7 @@ async def async_remove_discovery_payload(
after a restart of Home Assistant.
"""
discovery_topic = discovery_data[ATTR_DISCOVERY_TOPIC]
await async_publish(hass, discovery_topic, "", retain=True)
await async_publish(hass, discovery_topic, None, retain=True)
async def async_clear_discovery_topic_if_entity_removed(

View File

@ -294,7 +294,7 @@ async def test_cleanup_device_tracker(
# Verify retained discovery topic has been cleared
mqtt_mock.async_publish.assert_called_once_with(
"homeassistant/device_tracker/bla/config", "", 0, True
"homeassistant/device_tracker/bla/config", None, 0, True
)

View File

@ -1358,7 +1358,7 @@ async def test_cleanup_trigger(
# Verify retained discovery topic has been cleared
mqtt_mock.async_publish.assert_called_once_with(
"homeassistant/device_automation/bla/config", "", 0, True
"homeassistant/device_automation/bla/config", None, 0, True
)

View File

@ -829,7 +829,7 @@ async def test_cleanup_device(
entity_registry: er.EntityRegistry,
mqtt_mock_entry: MqttMockHAClientGenerator,
) -> None:
"""Test discvered device is cleaned up when entry removed from device."""
"""Test discovered device is cleaned up when entry removed from device."""
mqtt_mock = await mqtt_mock_entry()
assert await async_setup_component(hass, "config", {})
ws_client = await hass_ws_client(hass)
@ -874,7 +874,7 @@ async def test_cleanup_device(
# Verify retained discovery topic has been cleared
mqtt_mock.async_publish.assert_called_once_with(
"homeassistant/sensor/bla/config", "", 0, True
"homeassistant/sensor/bla/config", None, 0, True
)
@ -1015,9 +1015,9 @@ async def test_cleanup_device_multiple_config_entries(
# Verify retained discovery topic has been cleared
mqtt_mock.async_publish.assert_has_calls(
[
call("homeassistant/sensor/bla/config", "", 0, True),
call("homeassistant/tag/bla/config", "", 0, True),
call("homeassistant/device_automation/bla/config", "", 0, True),
call("homeassistant/sensor/bla/config", None, 0, True),
call("homeassistant/tag/bla/config", None, 0, True),
call("homeassistant/device_automation/bla/config", None, 0, True),
],
any_order=True,
)
@ -1616,11 +1616,11 @@ async def test_clear_config_topic_disabled_entity(
# Assert all valid discovery topics are cleared
assert mqtt_mock.async_publish.call_count == 2
assert (
call("homeassistant/sensor/sbfspot_0/sbfspot_12345/config", "", 0, True)
call("homeassistant/sensor/sbfspot_0/sbfspot_12345/config", None, 0, True)
in mqtt_mock.async_publish.mock_calls
)
assert (
call("homeassistant/sensor/sbfspot_0/sbfspot_12345_1/config", "", 0, True)
call("homeassistant/sensor/sbfspot_0/sbfspot_12345_1/config", None, 0, True)
in mqtt_mock.async_publish.mock_calls
)

View File

@ -223,49 +223,50 @@ async def test_publish(
) -> None:
"""Test the publish function."""
mqtt_mock = await mqtt_mock_entry()
publish_mock: MagicMock = mqtt_mock._mqttc.publish
await mqtt.async_publish(hass, "test-topic", "test-payload")
await hass.async_block_till_done()
assert mqtt_mock.async_publish.called
assert mqtt_mock.async_publish.call_args[0] == (
assert publish_mock.called
assert publish_mock.call_args[0] == (
"test-topic",
"test-payload",
0,
False,
)
mqtt_mock.reset_mock()
publish_mock.reset_mock()
await mqtt.async_publish(hass, "test-topic", "test-payload", 2, True)
await hass.async_block_till_done()
assert mqtt_mock.async_publish.called
assert mqtt_mock.async_publish.call_args[0] == (
assert publish_mock.called
assert publish_mock.call_args[0] == (
"test-topic",
"test-payload",
2,
True,
)
mqtt_mock.reset_mock()
publish_mock.reset_mock()
mqtt.publish(hass, "test-topic2", "test-payload2")
await hass.async_block_till_done()
assert mqtt_mock.async_publish.called
assert mqtt_mock.async_publish.call_args[0] == (
assert publish_mock.called
assert publish_mock.call_args[0] == (
"test-topic2",
"test-payload2",
0,
False,
)
mqtt_mock.reset_mock()
publish_mock.reset_mock()
mqtt.publish(hass, "test-topic2", "test-payload2", 2, True)
await hass.async_block_till_done()
assert mqtt_mock.async_publish.called
assert mqtt_mock.async_publish.call_args[0] == (
assert publish_mock.called
assert publish_mock.call_args[0] == (
"test-topic2",
"test-payload2",
2,
True,
)
mqtt_mock.reset_mock()
publish_mock.reset_mock()
# test binary pass-through
mqtt.publish(
@ -276,8 +277,8 @@ async def test_publish(
False,
)
await hass.async_block_till_done()
assert mqtt_mock.async_publish.called
assert mqtt_mock.async_publish.call_args[0] == (
assert publish_mock.called
assert publish_mock.call_args[0] == (
"test-topic3",
b"\xde\xad\xbe\xef",
0,
@ -285,6 +286,25 @@ async def test_publish(
)
mqtt_mock.reset_mock()
# test null payload
mqtt.publish(
hass,
"test-topic3",
None,
0,
False,
)
await hass.async_block_till_done()
assert publish_mock.called
assert publish_mock.call_args[0] == (
"test-topic3",
None,
0,
False,
)
publish_mock.reset_mock()
async def test_convert_outgoing_payload(hass: HomeAssistant) -> None:
"""Test the converting of outgoing MQTT payloads without template."""

View File

@ -623,7 +623,7 @@ async def test_cleanup_tag(
# Verify retained discovery topic has been cleared
mqtt_mock.async_publish.assert_called_once_with(
"homeassistant/tag/bla1/config", "", 0, True
"homeassistant/tag/bla1/config", None, 0, True
)

View File

@ -927,7 +927,7 @@ def mqtt_client_mock(hass: HomeAssistant) -> Generator[MqttMockPahoClient, None,
@ha.callback
def _async_fire_mqtt_message(topic, payload, qos, retain):
async_fire_mqtt_message(hass, topic, payload, qos, retain)
async_fire_mqtt_message(hass, topic, payload or b"", qos, retain)
mid = get_mid()
hass.loop.call_soon(mock_client.on_publish, 0, 0, mid)
return FakeInfo(mid)