diff --git a/homeassistant/components/mqtt/client.py b/homeassistant/components/mqtt/client.py index 67d5bb2d49d..70e6f573266 100644 --- a/homeassistant/components/mqtt/client.py +++ b/homeassistant/components/mqtt/client.py @@ -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( ( diff --git a/homeassistant/components/mqtt/mixins.py b/homeassistant/components/mqtt/mixins.py index 090433c7327..193c45d67f8 100644 --- a/homeassistant/components/mqtt/mixins.py +++ b/homeassistant/components/mqtt/mixins.py @@ -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( diff --git a/tests/components/mqtt/test_device_tracker.py b/tests/components/mqtt/test_device_tracker.py index 80fbd754d2c..254885919b0 100644 --- a/tests/components/mqtt/test_device_tracker.py +++ b/tests/components/mqtt/test_device_tracker.py @@ -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 ) diff --git a/tests/components/mqtt/test_device_trigger.py b/tests/components/mqtt/test_device_trigger.py index b01e40d311e..9e75ea5168b 100644 --- a/tests/components/mqtt/test_device_trigger.py +++ b/tests/components/mqtt/test_device_trigger.py @@ -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 ) diff --git a/tests/components/mqtt/test_discovery.py b/tests/components/mqtt/test_discovery.py index 32a6488b438..2e1f78c1bd4 100644 --- a/tests/components/mqtt/test_discovery.py +++ b/tests/components/mqtt/test_discovery.py @@ -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 ) diff --git a/tests/components/mqtt/test_init.py b/tests/components/mqtt/test_init.py index 0a27c48834a..13130329296 100644 --- a/tests/components/mqtt/test_init.py +++ b/tests/components/mqtt/test_init.py @@ -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.""" diff --git a/tests/components/mqtt/test_tag.py b/tests/components/mqtt/test_tag.py index 9de3b27fc3d..1575684e164 100644 --- a/tests/components/mqtt/test_tag.py +++ b/tests/components/mqtt/test_tag.py @@ -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 ) diff --git a/tests/conftest.py b/tests/conftest.py index 7184456e296..5d992297855 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -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)