Fix blocking I/O of SSLContext.load_default_certs in Ecovacs (#123856)

This commit is contained in:
Robert Resch 2024-08-14 15:55:59 +02:00 committed by GitHub
parent e33a7ecefa
commit c761d75550
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 31 additions and 19 deletions

View file

@ -2,6 +2,7 @@
from __future__ import annotations from __future__ import annotations
from functools import partial
import logging import logging
import ssl import ssl
from typing import Any from typing import Any
@ -100,12 +101,15 @@ async def _validate_input(
if not user_input.get(CONF_VERIFY_MQTT_CERTIFICATE, True) and mqtt_url: if not user_input.get(CONF_VERIFY_MQTT_CERTIFICATE, True) and mqtt_url:
ssl_context = get_default_no_verify_context() ssl_context = get_default_no_verify_context()
mqtt_config = create_mqtt_config( mqtt_config = await hass.async_add_executor_job(
partial(
create_mqtt_config,
device_id=device_id, device_id=device_id,
country=country, country=country,
override_mqtt_url=mqtt_url, override_mqtt_url=mqtt_url,
ssl_context=ssl_context, ssl_context=ssl_context,
) )
)
client = MqttClient(mqtt_config, authenticator) client = MqttClient(mqtt_config, authenticator)
cannot_connect_field = CONF_OVERRIDE_MQTT_URL if mqtt_url else "base" cannot_connect_field = CONF_OVERRIDE_MQTT_URL if mqtt_url else "base"

View file

@ -3,6 +3,7 @@
from __future__ import annotations from __future__ import annotations
from collections.abc import Mapping from collections.abc import Mapping
from functools import partial
import logging import logging
import ssl import ssl
from typing import Any from typing import Any
@ -64,32 +65,28 @@ class EcovacsController:
if not config.get(CONF_VERIFY_MQTT_CERTIFICATE, True) and mqtt_url: if not config.get(CONF_VERIFY_MQTT_CERTIFICATE, True) and mqtt_url:
ssl_context = get_default_no_verify_context() ssl_context = get_default_no_verify_context()
self._mqtt = MqttClient( self._mqtt_config_fn = partial(
create_mqtt_config( create_mqtt_config,
device_id=self._device_id, device_id=self._device_id,
country=country, country=country,
override_mqtt_url=mqtt_url, override_mqtt_url=mqtt_url,
ssl_context=ssl_context, ssl_context=ssl_context,
),
self._authenticator,
) )
self._mqtt_client: MqttClient | None = None
self._added_legacy_entities: set[str] = set() self._added_legacy_entities: set[str] = set()
async def initialize(self) -> None: async def initialize(self) -> None:
"""Init controller.""" """Init controller."""
mqtt_config_verfied = False
try: try:
devices = await self._api_client.get_devices() devices = await self._api_client.get_devices()
credentials = await self._authenticator.authenticate() credentials = await self._authenticator.authenticate()
for device_config in devices: for device_config in devices:
if isinstance(device_config, DeviceInfo): if isinstance(device_config, DeviceInfo):
# MQTT device # MQTT device
if not mqtt_config_verfied:
await self._mqtt.verify_config()
mqtt_config_verfied = True
device = Device(device_config, self._authenticator) device = Device(device_config, self._authenticator)
await device.initialize(self._mqtt) mqtt = await self._get_mqtt_client()
await device.initialize(mqtt)
self._devices.append(device) self._devices.append(device)
else: else:
# Legacy device # Legacy device
@ -116,7 +113,8 @@ class EcovacsController:
await device.teardown() await device.teardown()
for legacy_device in self._legacy_devices: for legacy_device in self._legacy_devices:
await self._hass.async_add_executor_job(legacy_device.disconnect) await self._hass.async_add_executor_job(legacy_device.disconnect)
await self._mqtt.disconnect() if self._mqtt_client is not None:
await self._mqtt_client.disconnect()
await self._authenticator.teardown() await self._authenticator.teardown()
def add_legacy_entity(self, device: VacBot, component: str) -> None: def add_legacy_entity(self, device: VacBot, component: str) -> None:
@ -127,6 +125,16 @@ class EcovacsController:
"""Check if legacy entity is added.""" """Check if legacy entity is added."""
return f"{device.vacuum['did']}_{component}" in self._added_legacy_entities return f"{device.vacuum['did']}_{component}" in self._added_legacy_entities
async def _get_mqtt_client(self) -> MqttClient:
"""Return validated MQTT client."""
if self._mqtt_client is None:
config = await self._hass.async_add_executor_job(self._mqtt_config_fn)
mqtt = MqttClient(config, self._authenticator)
await mqtt.verify_config()
self._mqtt_client = mqtt
return self._mqtt_client
@property @property
def devices(self) -> list[Device]: def devices(self) -> list[Device]:
"""Return devices.""" """Return devices."""