Gracefully disconnect MQTT entry if entry is reloaded (#119753)

This commit is contained in:
Jan Bouwhuis 2024-06-18 09:29:22 +02:00 committed by GitHub
parent 67223b2a2d
commit 6eb9d1e01d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 17 additions and 6 deletions

View File

@ -535,8 +535,8 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
registry_hooks = mqtt_data.discovery_registry_hooks registry_hooks = mqtt_data.discovery_registry_hooks
while registry_hooks: while registry_hooks:
registry_hooks.popitem()[1]() registry_hooks.popitem()[1]()
# Wait for all ACKs and stop the loop # Wait for all ACKs, stop the loop and disconnect the client
await mqtt_client.async_disconnect() await mqtt_client.async_disconnect(disconnect_paho_client=True)
# Cleanup MQTT client availability # Cleanup MQTT client availability
hass.data.pop(DATA_MQTT_AVAILABLE, None) hass.data.pop(DATA_MQTT_AVAILABLE, None)

View File

@ -803,8 +803,12 @@ class MQTT:
await asyncio.sleep(RECONNECT_INTERVAL_SECONDS) await asyncio.sleep(RECONNECT_INTERVAL_SECONDS)
async def async_disconnect(self) -> None: async def async_disconnect(self, disconnect_paho_client: bool = False) -> None:
"""Stop the MQTT client.""" """Stop the MQTT client.
We only disconnect grafully if disconnect_paho_client is set, but not
when Home Assistant is shut down.
"""
# stop waiting for any pending subscriptions # stop waiting for any pending subscriptions
await self._subscribe_debouncer.async_cleanup() await self._subscribe_debouncer.async_cleanup()
@ -824,7 +828,9 @@ class MQTT:
self._should_reconnect = False self._should_reconnect = False
self._async_cancel_reconnect() self._async_cancel_reconnect()
# We do not gracefully disconnect to ensure # We do not gracefully disconnect to ensure
# the broker publishes the will message # the broker publishes the will message unless the entry is reloaded
if disconnect_paho_client:
self._mqttc.disconnect()
@callback @callback
def async_restore_tracked_subscriptions( def async_restore_tracked_subscriptions(
@ -1274,7 +1280,8 @@ class MQTT:
self._async_connection_result(False) self._async_connection_result(False)
self.connected = False self.connected = False
async_dispatcher_send(self.hass, MQTT_CONNECTION_STATE, False) async_dispatcher_send(self.hass, MQTT_CONNECTION_STATE, False)
_LOGGER.warning( _LOGGER.log(
logging.INFO if result_code == 0 else logging.DEBUG,
"Disconnected from MQTT server %s:%s (%s)", "Disconnected from MQTT server %s:%s (%s)",
self.conf[CONF_BROKER], self.conf[CONF_BROKER],
self.conf.get(CONF_PORT, DEFAULT_PORT), self.conf.get(CONF_PORT, DEFAULT_PORT),

View File

@ -4087,6 +4087,7 @@ async def test_link_config_entry(
async def test_reload_config_entry( async def test_reload_config_entry(
hass: HomeAssistant, hass: HomeAssistant,
mqtt_mock_entry: MqttMockHAClientGenerator, mqtt_mock_entry: MqttMockHAClientGenerator,
caplog: pytest.LogCaptureFixture,
) -> None: ) -> None:
"""Test manual entities reloaded and set up correctly.""" """Test manual entities reloaded and set up correctly."""
await mqtt_mock_entry() await mqtt_mock_entry()
@ -4153,6 +4154,9 @@ async def test_reload_config_entry(
assert await hass.config_entries.async_reload(entry.entry_id) assert await hass.config_entries.async_reload(entry.entry_id)
assert entry.state is ConfigEntryState.LOADED assert entry.state is ConfigEntryState.LOADED
await hass.async_block_till_done() await hass.async_block_till_done()
# Assert the MQTT client was connected gracefully
with caplog.at_level(logging.INFO):
assert "Disconnected from MQTT server mock-broker:1883" in caplog.text
assert (state := hass.states.get("sensor.test_manual1")) is not None assert (state := hass.states.get("sensor.test_manual1")) is not None
assert state.attributes["friendly_name"] == "test_manual1_updated" assert state.attributes["friendly_name"] == "test_manual1_updated"