diff --git a/homeassistant/components/automation/__init__.py b/homeassistant/components/automation/__init__.py index c743e1f83fd..1914a837ba7 100644 --- a/homeassistant/components/automation/__init__.py +++ b/homeassistant/components/automation/__init__.py @@ -36,6 +36,7 @@ from homeassistant.core import ( HomeAssistant, callback, split_entity_id, + valid_entity_id, ) from homeassistant.exceptions import ( ConditionError, @@ -361,7 +362,7 @@ class AutomationEntity(ToggleEntity, RestoreEntity): referenced |= condition.async_extract_devices(conf) for conf in self._trigger_config: - referenced |= set(_trigger_extract_device(conf)) + referenced |= set(_trigger_extract_devices(conf)) self._referenced_devices = referenced return referenced @@ -763,7 +764,7 @@ async def _async_process_if(hass, name, config, p_config): @callback -def _trigger_extract_device(trigger_conf: dict) -> list[str]: +def _trigger_extract_devices(trigger_conf: dict) -> list[str]: """Extract devices from a trigger config.""" if trigger_conf[CONF_PLATFORM] == "device": return [trigger_conf[CONF_DEVICE_ID]] @@ -772,6 +773,7 @@ def _trigger_extract_device(trigger_conf: dict) -> list[str]: trigger_conf[CONF_PLATFORM] == "event" and CONF_EVENT_DATA in trigger_conf and CONF_DEVICE_ID in trigger_conf[CONF_EVENT_DATA] + and isinstance(trigger_conf[CONF_EVENT_DATA][CONF_DEVICE_ID], str) ): return [trigger_conf[CONF_EVENT_DATA][CONF_DEVICE_ID]] @@ -803,6 +805,8 @@ def _trigger_extract_entities(trigger_conf: dict) -> list[str]: trigger_conf[CONF_PLATFORM] == "event" and CONF_EVENT_DATA in trigger_conf and CONF_ENTITY_ID in trigger_conf[CONF_EVENT_DATA] + and isinstance(trigger_conf[CONF_EVENT_DATA][CONF_ENTITY_ID], str) + and valid_entity_id(trigger_conf[CONF_EVENT_DATA][CONF_ENTITY_ID]) ): return [trigger_conf[CONF_EVENT_DATA][CONF_ENTITY_ID]] diff --git a/homeassistant/components/bluetooth/__init__.py b/homeassistant/components/bluetooth/__init__.py index 2d7b47b7552..f9c6a6aca15 100644 --- a/homeassistant/components/bluetooth/__init__.py +++ b/homeassistant/components/bluetooth/__init__.py @@ -358,13 +358,13 @@ class BluetoothManager: async with async_timeout.timeout(START_TIMEOUT): await self.scanner.start() # type: ignore[no-untyped-call] except InvalidMessageError as ex: - self._cancel_device_detected() + self._async_cancel_scanner_callback() _LOGGER.debug("Invalid DBus message received: %s", ex, exc_info=True) raise ConfigEntryNotReady( f"Invalid DBus message received: {ex}; try restarting `dbus`" ) from ex except BrokenPipeError as ex: - self._cancel_device_detected() + self._async_cancel_scanner_callback() _LOGGER.debug("DBus connection broken: %s", ex, exc_info=True) if is_docker_env(): raise ConfigEntryNotReady( @@ -374,7 +374,7 @@ class BluetoothManager: f"DBus connection broken: {ex}; try restarting `bluetooth` and `dbus`" ) from ex except FileNotFoundError as ex: - self._cancel_device_detected() + self._async_cancel_scanner_callback() _LOGGER.debug( "FileNotFoundError while starting bluetooth: %s", ex, exc_info=True ) @@ -386,12 +386,12 @@ class BluetoothManager: f"DBus service not found; make sure the DBus socket is available to Home Assistant: {ex}" ) from ex except asyncio.TimeoutError as ex: - self._cancel_device_detected() + self._async_cancel_scanner_callback() raise ConfigEntryNotReady( f"Timed out starting Bluetooth after {START_TIMEOUT} seconds" ) from ex except BleakError as ex: - self._cancel_device_detected() + self._async_cancel_scanner_callback() _LOGGER.debug("BleakError while starting bluetooth: %s", ex, exc_info=True) raise ConfigEntryNotReady(f"Failed to start Bluetooth: {ex}") from ex self.async_setup_unavailable_tracking() @@ -573,15 +573,20 @@ class BluetoothManager: self._cancel_stop = None await self.async_stop() + @hass_callback + def _async_cancel_scanner_callback(self) -> None: + """Cancel the scanner callback.""" + if self._cancel_device_detected: + self._cancel_device_detected() + self._cancel_device_detected = None + async def async_stop(self) -> None: """Stop bluetooth discovery.""" _LOGGER.debug("Stopping bluetooth discovery") if self._cancel_watchdog: self._cancel_watchdog() self._cancel_watchdog = None - if self._cancel_device_detected: - self._cancel_device_detected() - self._cancel_device_detected = None + self._async_cancel_scanner_callback() if self._cancel_unavailable_tracking: self._cancel_unavailable_tracking() self._cancel_unavailable_tracking = None diff --git a/homeassistant/components/bmw_connected_drive/manifest.json b/homeassistant/components/bmw_connected_drive/manifest.json index 0381035a63e..f540176a837 100644 --- a/homeassistant/components/bmw_connected_drive/manifest.json +++ b/homeassistant/components/bmw_connected_drive/manifest.json @@ -2,7 +2,7 @@ "domain": "bmw_connected_drive", "name": "BMW Connected Drive", "documentation": "https://www.home-assistant.io/integrations/bmw_connected_drive", - "requirements": ["bimmer_connected==0.10.1"], + "requirements": ["bimmer_connected==0.10.2"], "codeowners": ["@gerard33", "@rikroe"], "config_flow": true, "iot_class": "cloud_polling", diff --git a/homeassistant/components/google/calendar.py b/homeassistant/components/google/calendar.py index ca98b3da087..77ed922e511 100644 --- a/homeassistant/components/google/calendar.py +++ b/homeassistant/components/google/calendar.py @@ -192,7 +192,6 @@ async def async_setup_entry( calendar_id, data.get(CONF_SEARCH), ) - await coordinator.async_config_entry_first_refresh() entities.append( GoogleCalendarEntity( coordinator, @@ -342,6 +341,9 @@ class GoogleCalendarEntity(CoordinatorEntity, CalendarEntity): async def async_added_to_hass(self) -> None: """When entity is added to hass.""" await super().async_added_to_hass() + # We do not ask for an update with async_add_entities() + # because it will update disabled entities + await self.coordinator.async_request_refresh() self._apply_coordinator_update() async def async_get_events( diff --git a/homeassistant/components/home_connect/__init__.py b/homeassistant/components/home_connect/__init__.py index 6e664ad07e4..0fa14682f44 100644 --- a/homeassistant/components/home_connect/__init__.py +++ b/homeassistant/components/home_connect/__init__.py @@ -138,11 +138,18 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: """Execute calls to services taking a program.""" program = call.data[ATTR_PROGRAM] device_id = call.data[ATTR_DEVICE_ID] - options = { - ATTR_KEY: call.data.get(ATTR_KEY), - ATTR_VALUE: call.data.get(ATTR_VALUE), - ATTR_UNIT: call.data.get(ATTR_UNIT), - } + + options = [] + + option_key = call.data.get(ATTR_KEY) + if option_key is not None: + option = {ATTR_KEY: option_key, ATTR_VALUE: call.data[ATTR_VALUE]} + + option_unit = call.data.get(ATTR_UNIT) + if option_unit is not None: + option[ATTR_UNIT] = option_unit + + options.append(option) appliance = _get_appliance_by_device_id(hass, device_id) await hass.async_add_executor_job(getattr(appliance, method), program, options) diff --git a/homeassistant/components/home_connect/manifest.json b/homeassistant/components/home_connect/manifest.json index ca6e0f012ac..c9aa5d229b8 100644 --- a/homeassistant/components/home_connect/manifest.json +++ b/homeassistant/components/home_connect/manifest.json @@ -4,7 +4,7 @@ "documentation": "https://www.home-assistant.io/integrations/home_connect", "dependencies": ["application_credentials"], "codeowners": ["@DavidMStraub"], - "requirements": ["homeconnect==0.7.1"], + "requirements": ["homeconnect==0.7.2"], "config_flow": true, "iot_class": "cloud_push", "loggers": ["homeconnect"] diff --git a/homeassistant/components/homekit_controller/manifest.json b/homeassistant/components/homekit_controller/manifest.json index 4bd9a0b70f9..ece53d29406 100644 --- a/homeassistant/components/homekit_controller/manifest.json +++ b/homeassistant/components/homekit_controller/manifest.json @@ -3,7 +3,7 @@ "name": "HomeKit Controller", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/homekit_controller", - "requirements": ["aiohomekit==1.2.9"], + "requirements": ["aiohomekit==1.2.11"], "zeroconf": ["_hap._tcp.local.", "_hap._udp.local."], "bluetooth": [{ "manufacturer_id": 76, "manufacturer_data_start": [6] }], "dependencies": ["bluetooth", "zeroconf"], diff --git a/homeassistant/components/hue/manifest.json b/homeassistant/components/hue/manifest.json index b3dbe4df50a..3854b861c98 100644 --- a/homeassistant/components/hue/manifest.json +++ b/homeassistant/components/hue/manifest.json @@ -3,7 +3,7 @@ "name": "Philips Hue", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/hue", - "requirements": ["aiohue==4.4.2"], + "requirements": ["aiohue==4.5.0"], "ssdp": [ { "manufacturer": "Royal Philips Electronics", diff --git a/homeassistant/components/inkbird/manifest.json b/homeassistant/components/inkbird/manifest.json index b0ef08143c2..f65177ab6e2 100644 --- a/homeassistant/components/inkbird/manifest.json +++ b/homeassistant/components/inkbird/manifest.json @@ -10,7 +10,7 @@ { "local_name": "xBBQ*" }, { "local_name": "tps" } ], - "requirements": ["inkbird-ble==0.5.2"], + "requirements": ["inkbird-ble==0.5.5"], "dependencies": ["bluetooth"], "codeowners": ["@bdraco"], "iot_class": "local_push" diff --git a/homeassistant/components/knx/manifest.json b/homeassistant/components/knx/manifest.json index 266eceaacee..0f9b6b4b95a 100644 --- a/homeassistant/components/knx/manifest.json +++ b/homeassistant/components/knx/manifest.json @@ -3,7 +3,7 @@ "name": "KNX", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/knx", - "requirements": ["xknx==0.22.1"], + "requirements": ["xknx==1.0.0"], "codeowners": ["@Julius2342", "@farmio", "@marvin-w"], "quality_scale": "platinum", "iot_class": "local_push", diff --git a/homeassistant/components/lifx/config_flow.py b/homeassistant/components/lifx/config_flow.py index 30b42e640f8..deff53e06c6 100644 --- a/homeassistant/components/lifx/config_flow.py +++ b/homeassistant/components/lifx/config_flow.py @@ -119,18 +119,20 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): ) -> FlowResult: """Confirm discovery.""" assert self._discovered_device is not None + discovered = self._discovered_device _LOGGER.debug( "Confirming discovery: %s with serial %s", - self._discovered_device.label, + discovered.label, self.unique_id, ) if user_input is not None or self._async_discovered_pending_migration(): - return self._async_create_entry_from_device(self._discovered_device) + return self._async_create_entry_from_device(discovered) + self._abort_if_unique_id_configured(updates={CONF_HOST: discovered.ip_addr}) self._set_confirm_only() placeholders = { - "label": self._discovered_device.label, - "host": self._discovered_device.ip_addr, + "label": discovered.label, + "host": discovered.ip_addr, "serial": self.unique_id, } self.context["title_placeholders"] = placeholders diff --git a/homeassistant/components/motion_blinds/__init__.py b/homeassistant/components/motion_blinds/__init__.py index dfbc6ab74a7..a023fc05d14 100644 --- a/homeassistant/components/motion_blinds/__init__.py +++ b/homeassistant/components/motion_blinds/__init__.py @@ -121,8 +121,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: multicast_interface = entry.data.get(CONF_INTERFACE, DEFAULT_INTERFACE) wait_for_push = entry.options.get(CONF_WAIT_FOR_PUSH, DEFAULT_WAIT_FOR_PUSH) - entry.async_on_unload(entry.add_update_listener(update_listener)) - # Create multicast Listener async with setup_lock: if KEY_MULTICAST_LISTENER not in hass.data[DOMAIN]: @@ -213,6 +211,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) + entry.async_on_unload(entry.add_update_listener(update_listener)) + return True diff --git a/homeassistant/components/sensorpush/manifest.json b/homeassistant/components/sensorpush/manifest.json index a5d900aaf3b..906b5c22f6b 100644 --- a/homeassistant/components/sensorpush/manifest.json +++ b/homeassistant/components/sensorpush/manifest.json @@ -8,7 +8,7 @@ "local_name": "SensorPush*" } ], - "requirements": ["sensorpush-ble==1.5.1"], + "requirements": ["sensorpush-ble==1.5.2"], "dependencies": ["bluetooth"], "codeowners": ["@bdraco"], "iot_class": "local_push" diff --git a/homeassistant/components/switchbot/manifest.json b/homeassistant/components/switchbot/manifest.json index b413b44d605..e70f467ae74 100644 --- a/homeassistant/components/switchbot/manifest.json +++ b/homeassistant/components/switchbot/manifest.json @@ -2,7 +2,7 @@ "domain": "switchbot", "name": "SwitchBot", "documentation": "https://www.home-assistant.io/integrations/switchbot", - "requirements": ["PySwitchbot==0.18.4"], + "requirements": ["PySwitchbot==0.18.10"], "config_flow": true, "dependencies": ["bluetooth"], "codeowners": [ diff --git a/homeassistant/components/system_bridge/__init__.py b/homeassistant/components/system_bridge/__init__.py index 19bcc224a66..74be1faed40 100644 --- a/homeassistant/components/system_bridge/__init__.py +++ b/homeassistant/components/system_bridge/__init__.py @@ -10,6 +10,10 @@ from systembridgeconnector.exceptions import ( ConnectionClosedException, ConnectionErrorException, ) +from systembridgeconnector.models.keyboard_key import KeyboardKey +from systembridgeconnector.models.keyboard_text import KeyboardText +from systembridgeconnector.models.open_path import OpenPath +from systembridgeconnector.models.open_url import OpenUrl from systembridgeconnector.version import SUPPORTED_VERSION, Version import voluptuous as vol @@ -149,7 +153,9 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: coordinator: SystemBridgeDataUpdateCoordinator = hass.data[DOMAIN][ call.data[CONF_BRIDGE] ] - await coordinator.websocket_client.open_path(call.data[CONF_PATH]) + await coordinator.websocket_client.open_path( + OpenPath(path=call.data[CONF_PATH]) + ) async def handle_open_url(call: ServiceCall) -> None: """Handle the open url service call.""" @@ -157,21 +163,25 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: coordinator: SystemBridgeDataUpdateCoordinator = hass.data[DOMAIN][ call.data[CONF_BRIDGE] ] - await coordinator.websocket_client.open_url(call.data[CONF_URL]) + await coordinator.websocket_client.open_url(OpenUrl(url=call.data[CONF_URL])) async def handle_send_keypress(call: ServiceCall) -> None: """Handle the send_keypress service call.""" coordinator: SystemBridgeDataUpdateCoordinator = hass.data[DOMAIN][ call.data[CONF_BRIDGE] ] - await coordinator.websocket_client.keyboard_keypress(call.data[CONF_KEY]) + await coordinator.websocket_client.keyboard_keypress( + KeyboardKey(key=call.data[CONF_KEY]) + ) async def handle_send_text(call: ServiceCall) -> None: """Handle the send_keypress service call.""" coordinator: SystemBridgeDataUpdateCoordinator = hass.data[DOMAIN][ call.data[CONF_BRIDGE] ] - await coordinator.websocket_client.keyboard_text(call.data[CONF_TEXT]) + await coordinator.websocket_client.keyboard_text( + KeyboardText(text=call.data[CONF_TEXT]) + ) hass.services.async_register( DOMAIN, diff --git a/homeassistant/components/system_bridge/config_flow.py b/homeassistant/components/system_bridge/config_flow.py index 9d89cf83288..995df6391cc 100644 --- a/homeassistant/components/system_bridge/config_flow.py +++ b/homeassistant/components/system_bridge/config_flow.py @@ -7,12 +7,13 @@ import logging from typing import Any import async_timeout -from systembridgeconnector.const import EVENT_MODULE, EVENT_TYPE, TYPE_DATA_UPDATE from systembridgeconnector.exceptions import ( AuthenticationException, ConnectionClosedException, ConnectionErrorException, ) +from systembridgeconnector.models.get_data import GetData +from systembridgeconnector.models.system import System from systembridgeconnector.websocket_client import WebSocketClient import voluptuous as vol @@ -38,7 +39,7 @@ STEP_USER_DATA_SCHEMA = vol.Schema( ) -async def validate_input( +async def _validate_input( hass: HomeAssistant, data: dict[str, Any], ) -> dict[str, str]: @@ -56,15 +57,12 @@ async def validate_input( try: async with async_timeout.timeout(30): await websocket_client.connect(session=async_get_clientsession(hass)) - await websocket_client.get_data(["system"]) - while True: - message = await websocket_client.receive_message() - _LOGGER.debug("Message: %s", message) - if ( - message[EVENT_TYPE] == TYPE_DATA_UPDATE - and message[EVENT_MODULE] == "system" - ): - break + hass.async_create_task(websocket_client.listen()) + response = await websocket_client.get_data(GetData(modules=["system"])) + _LOGGER.debug("Got response: %s", response.json()) + if response.data is None or not isinstance(response.data, System): + raise CannotConnect("No data received") + system: System = response.data except AuthenticationException as exception: _LOGGER.warning( "Authentication error when connecting to %s: %s", data[CONF_HOST], exception @@ -81,14 +79,12 @@ async def validate_input( except asyncio.TimeoutError as exception: _LOGGER.warning("Timed out connecting to %s: %s", data[CONF_HOST], exception) raise CannotConnect from exception + except ValueError as exception: + raise CannotConnect from exception - _LOGGER.debug("%s Message: %s", TYPE_DATA_UPDATE, message) + _LOGGER.debug("Got System data: %s", system.json()) - if "uuid" not in message["data"]: - error = "No UUID in result!" - raise CannotConnect(error) - - return {"hostname": host, "uuid": message["data"]["uuid"]} + return {"hostname": host, "uuid": system.uuid} async def _async_get_info( @@ -98,7 +94,7 @@ async def _async_get_info( errors = {} try: - info = await validate_input(hass, user_input) + info = await _validate_input(hass, user_input) except CannotConnect: errors["base"] = "cannot_connect" except InvalidAuth: diff --git a/homeassistant/components/system_bridge/coordinator.py b/homeassistant/components/system_bridge/coordinator.py index 1719d951cf0..695dca44342 100644 --- a/homeassistant/components/system_bridge/coordinator.py +++ b/homeassistant/components/system_bridge/coordinator.py @@ -5,6 +5,7 @@ import asyncio from collections.abc import Callable from datetime import timedelta import logging +from typing import Any import async_timeout from pydantic import BaseModel # pylint: disable=no-name-in-module @@ -17,8 +18,10 @@ from systembridgeconnector.models.battery import Battery from systembridgeconnector.models.cpu import Cpu from systembridgeconnector.models.disk import Disk from systembridgeconnector.models.display import Display +from systembridgeconnector.models.get_data import GetData from systembridgeconnector.models.gpu import Gpu from systembridgeconnector.models.memory import Memory +from systembridgeconnector.models.register_data_listener import RegisterDataListener from systembridgeconnector.models.system import System from systembridgeconnector.websocket_client import WebSocketClient @@ -93,12 +96,14 @@ class SystemBridgeDataUpdateCoordinator( if not self.websocket_client.connected: await self._setup_websocket() - self.hass.async_create_task(self.websocket_client.get_data(modules)) + self.hass.async_create_task( + self.websocket_client.get_data(GetData(modules=modules)) + ) async def async_handle_module( self, module_name: str, - module, + module: Any, ) -> None: """Handle data from the WebSocket client.""" self.logger.debug("Set new data for: %s", module_name) @@ -174,7 +179,9 @@ class SystemBridgeDataUpdateCoordinator( self.hass.async_create_task(self._listen_for_data()) - await self.websocket_client.register_data_listener(MODULES) + await self.websocket_client.register_data_listener( + RegisterDataListener(modules=MODULES) + ) self.last_update_success = True self.async_update_listeners() diff --git a/homeassistant/components/system_bridge/manifest.json b/homeassistant/components/system_bridge/manifest.json index 4fb2201e2c7..7968b588814 100644 --- a/homeassistant/components/system_bridge/manifest.json +++ b/homeassistant/components/system_bridge/manifest.json @@ -3,7 +3,7 @@ "name": "System Bridge", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/system_bridge", - "requirements": ["systembridgeconnector==3.3.2"], + "requirements": ["systembridgeconnector==3.4.4"], "codeowners": ["@timmo001"], "zeroconf": ["_system-bridge._tcp.local."], "after_dependencies": ["zeroconf"], diff --git a/homeassistant/const.py b/homeassistant/const.py index e79c132519d..329c0e483dd 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -7,7 +7,7 @@ from .backports.enum import StrEnum MAJOR_VERSION: Final = 2022 MINOR_VERSION: Final = 8 -PATCH_VERSION: Final = "4" +PATCH_VERSION: Final = "5" __short_version__: Final = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__: Final = f"{__short_version__}.{PATCH_VERSION}" REQUIRED_PYTHON_VER: Final[tuple[int, int, int]] = (3, 9, 0) diff --git a/pyproject.toml b/pyproject.toml index 6c6b88feb4a..b42b0b91b58 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "homeassistant" -version = "2022.8.4" +version = "2022.8.5" license = {text = "Apache-2.0"} description = "Open-source home automation platform running on Python 3." readme = "README.rst" diff --git a/requirements_all.txt b/requirements_all.txt index 96be4dae1b1..300ac05de84 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -37,7 +37,7 @@ PyRMVtransport==0.3.3 PySocks==1.7.1 # homeassistant.components.switchbot -PySwitchbot==0.18.4 +PySwitchbot==0.18.10 # homeassistant.components.transport_nsw PyTransportNSW==0.1.1 @@ -168,14 +168,14 @@ aioguardian==2022.07.0 aioharmony==0.2.9 # homeassistant.components.homekit_controller -aiohomekit==1.2.9 +aiohomekit==1.2.11 # homeassistant.components.emulated_hue # homeassistant.components.http aiohttp_cors==0.7.0 # homeassistant.components.hue -aiohue==4.4.2 +aiohue==4.5.0 # homeassistant.components.imap aioimaplib==1.0.0 @@ -399,7 +399,7 @@ beautifulsoup4==4.11.1 bellows==0.32.0 # homeassistant.components.bmw_connected_drive -bimmer_connected==0.10.1 +bimmer_connected==0.10.2 # homeassistant.components.bizkaibus bizkaibus==0.1.1 @@ -842,7 +842,7 @@ holidays==0.14.2 home-assistant-frontend==20220802.0 # homeassistant.components.home_connect -homeconnect==0.7.1 +homeconnect==0.7.2 # homeassistant.components.homematicip_cloud homematicip==1.0.7 @@ -902,7 +902,7 @@ influxdb-client==1.24.0 influxdb==5.3.1 # homeassistant.components.inkbird -inkbird-ble==0.5.2 +inkbird-ble==0.5.5 # homeassistant.components.insteon insteon-frontend-home-assistant==0.2.0 @@ -2160,7 +2160,7 @@ sendgrid==6.8.2 sense_energy==0.10.4 # homeassistant.components.sensorpush -sensorpush-ble==1.5.1 +sensorpush-ble==1.5.2 # homeassistant.components.sentry sentry-sdk==1.8.0 @@ -2281,7 +2281,7 @@ swisshydrodata==0.1.0 synology-srm==0.2.0 # homeassistant.components.system_bridge -systembridgeconnector==3.3.2 +systembridgeconnector==3.4.4 # homeassistant.components.tailscale tailscale==0.2.0 @@ -2473,7 +2473,7 @@ xboxapi==2.0.1 xiaomi-ble==0.6.4 # homeassistant.components.knx -xknx==0.22.1 +xknx==1.0.0 # homeassistant.components.bluesound # homeassistant.components.fritz diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 59b922c4ef1..a069c31b87b 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -33,7 +33,7 @@ PyRMVtransport==0.3.3 PySocks==1.7.1 # homeassistant.components.switchbot -PySwitchbot==0.18.4 +PySwitchbot==0.18.10 # homeassistant.components.transport_nsw PyTransportNSW==0.1.1 @@ -152,14 +152,14 @@ aioguardian==2022.07.0 aioharmony==0.2.9 # homeassistant.components.homekit_controller -aiohomekit==1.2.9 +aiohomekit==1.2.11 # homeassistant.components.emulated_hue # homeassistant.components.http aiohttp_cors==0.7.0 # homeassistant.components.hue -aiohue==4.4.2 +aiohue==4.5.0 # homeassistant.components.apache_kafka aiokafka==0.7.2 @@ -323,7 +323,7 @@ beautifulsoup4==4.11.1 bellows==0.32.0 # homeassistant.components.bmw_connected_drive -bimmer_connected==0.10.1 +bimmer_connected==0.10.2 # homeassistant.components.bluetooth bleak==0.15.1 @@ -619,7 +619,7 @@ holidays==0.14.2 home-assistant-frontend==20220802.0 # homeassistant.components.home_connect -homeconnect==0.7.1 +homeconnect==0.7.2 # homeassistant.components.homematicip_cloud homematicip==1.0.7 @@ -655,7 +655,7 @@ influxdb-client==1.24.0 influxdb==5.3.1 # homeassistant.components.inkbird -inkbird-ble==0.5.2 +inkbird-ble==0.5.5 # homeassistant.components.insteon insteon-frontend-home-assistant==0.2.0 @@ -1451,7 +1451,7 @@ securetar==2022.2.0 sense_energy==0.10.4 # homeassistant.components.sensorpush -sensorpush-ble==1.5.1 +sensorpush-ble==1.5.2 # homeassistant.components.sentry sentry-sdk==1.8.0 @@ -1539,7 +1539,7 @@ sunwatcher==0.2.1 surepy==0.7.2 # homeassistant.components.system_bridge -systembridgeconnector==3.3.2 +systembridgeconnector==3.4.4 # homeassistant.components.tailscale tailscale==0.2.0 @@ -1665,7 +1665,7 @@ xbox-webapi==2.0.11 xiaomi-ble==0.6.4 # homeassistant.components.knx -xknx==0.22.1 +xknx==1.0.0 # homeassistant.components.bluesound # homeassistant.components.fritz diff --git a/tests/components/automation/test_init.py b/tests/components/automation/test_init.py index bcbcf382892..cef553653de 100644 --- a/tests/components/automation/test_init.py +++ b/tests/components/automation/test_init.py @@ -1103,6 +1103,24 @@ async def test_extraction_functions(hass): "event_type": "state_changed", "event_data": {"entity_id": "sensor.trigger_event"}, }, + # entity_id is a list of strings (not supported) + { + "platform": "event", + "event_type": "state_changed", + "event_data": {"entity_id": ["sensor.trigger_event2"]}, + }, + # entity_id is not a valid entity ID + { + "platform": "event", + "event_type": "state_changed", + "event_data": {"entity_id": "abc"}, + }, + # entity_id is not a string + { + "platform": "event", + "event_type": "state_changed", + "event_data": {"entity_id": 123}, + }, ], "condition": { "condition": "state", @@ -1151,6 +1169,18 @@ async def test_extraction_functions(hass): "event_type": "esphome.button_pressed", "event_data": {"device_id": "device-trigger-event"}, }, + # device_id is a list of strings (not supported) + { + "platform": "event", + "event_type": "esphome.button_pressed", + "event_data": {"device_id": ["device-trigger-event"]}, + }, + # device_id is not a string + { + "platform": "event", + "event_type": "esphome.button_pressed", + "event_data": {"device_id": 123}, + }, ], "condition": { "condition": "device", diff --git a/tests/components/bluetooth/test_init.py b/tests/components/bluetooth/test_init.py index 9432be9f2e4..e69d7ba96e1 100644 --- a/tests/components/bluetooth/test_init.py +++ b/tests/components/bluetooth/test_init.py @@ -164,6 +164,43 @@ async def test_setup_and_retry_adapter_not_yet_available(hass, caplog): await hass.async_block_till_done() +async def test_no_race_during_manual_reload_in_retry_state(hass, caplog): + """Test we can successfully reload when the entry is in a retry state.""" + mock_bt = [] + with patch("homeassistant.components.bluetooth.HaBleakScanner.async_setup"), patch( + "homeassistant.components.bluetooth.HaBleakScanner.start", + side_effect=BleakError, + ), patch( + "homeassistant.components.bluetooth.async_get_bluetooth", return_value=mock_bt + ): + assert await async_setup_component( + hass, bluetooth.DOMAIN, {bluetooth.DOMAIN: {}} + ) + await hass.async_block_till_done() + hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED) + await hass.async_block_till_done() + + entry = hass.config_entries.async_entries(bluetooth.DOMAIN)[0] + + assert "Failed to start Bluetooth" in caplog.text + assert len(bluetooth.async_discovered_service_info(hass)) == 0 + assert entry.state == ConfigEntryState.SETUP_RETRY + + with patch( + "homeassistant.components.bluetooth.HaBleakScanner.start", + ): + await hass.config_entries.async_reload(entry.entry_id) + await hass.async_block_till_done() + + assert entry.state == ConfigEntryState.LOADED + + with patch( + "homeassistant.components.bluetooth.HaBleakScanner.stop", + ): + hass.bus.async_fire(EVENT_HOMEASSISTANT_STOP) + await hass.async_block_till_done() + + async def test_calling_async_discovered_devices_no_bluetooth(hass, caplog): """Test we fail gracefully when asking for discovered devices and there is no blueooth.""" mock_bt = [] @@ -828,6 +865,66 @@ async def test_register_callback_by_address( assert service_info.manufacturer_id == 89 +async def test_register_callback_survives_reload( + hass, mock_bleak_scanner_start, enable_bluetooth +): + """Test registering a callback by address survives bluetooth being reloaded.""" + mock_bt = [] + callbacks = [] + + def _fake_subscriber( + service_info: BluetoothServiceInfo, change: BluetoothChange + ) -> None: + """Fake subscriber for the BleakScanner.""" + callbacks.append((service_info, change)) + + with patch( + "homeassistant.components.bluetooth.async_get_bluetooth", return_value=mock_bt + ): + assert await async_setup_component( + hass, bluetooth.DOMAIN, {bluetooth.DOMAIN: {}} + ) + await hass.async_block_till_done() + + hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED) + await hass.async_block_till_done() + + bluetooth.async_register_callback( + hass, + _fake_subscriber, + {"address": "44:44:33:11:23:45"}, + BluetoothScanningMode.ACTIVE, + ) + + assert len(mock_bleak_scanner_start.mock_calls) == 1 + + switchbot_device = BLEDevice("44:44:33:11:23:45", "wohand") + switchbot_adv = AdvertisementData( + local_name="wohand", + service_uuids=["cba20d00-224d-11e6-9fb8-0002a5d5c51b"], + manufacturer_data={89: b"\xd8.\xad\xcd\r\x85"}, + service_data={"00000d00-0000-1000-8000-00805f9b34fb": b"H\x10c"}, + ) + + _get_underlying_scanner()._callback(switchbot_device, switchbot_adv) + assert len(callbacks) == 1 + service_info: BluetoothServiceInfo = callbacks[0][0] + assert service_info.name == "wohand" + assert service_info.manufacturer == "Nordic Semiconductor ASA" + assert service_info.manufacturer_id == 89 + + entry = hass.config_entries.async_entries(bluetooth.DOMAIN)[0] + await hass.config_entries.async_reload(entry.entry_id) + await hass.async_block_till_done() + + _get_underlying_scanner()._callback(switchbot_device, switchbot_adv) + assert len(callbacks) == 2 + service_info: BluetoothServiceInfo = callbacks[1][0] + assert service_info.name == "wohand" + assert service_info.manufacturer == "Nordic Semiconductor ASA" + assert service_info.manufacturer_id == 89 + + async def test_process_advertisements_bail_on_good_advertisement( hass: HomeAssistant, mock_bleak_scanner_start, enable_bluetooth ): diff --git a/tests/components/inkbird/test_config_flow.py b/tests/components/inkbird/test_config_flow.py index fe210f75f4b..4d9fbc65df7 100644 --- a/tests/components/inkbird/test_config_flow.py +++ b/tests/components/inkbird/test_config_flow.py @@ -25,7 +25,7 @@ async def test_async_step_bluetooth_valid_device(hass): result["flow_id"], user_input={} ) assert result2["type"] == FlowResultType.CREATE_ENTRY - assert result2["title"] == "iBBQ 6AADDD4CAC3D" + assert result2["title"] == "iBBQ AC3D" assert result2["data"] == {} assert result2["result"].unique_id == "4125DDBA-2774-4851-9889-6AADDD4CAC3D" @@ -69,7 +69,7 @@ async def test_async_step_user_with_found_devices(hass): user_input={"address": "61DE521B-F0BF-9F44-64D4-75BBE1738105"}, ) assert result2["type"] == FlowResultType.CREATE_ENTRY - assert result2["title"] == "IBS-TH 75BBE1738105" + assert result2["title"] == "IBS-TH 8105" assert result2["data"] == {} assert result2["result"].unique_id == "61DE521B-F0BF-9F44-64D4-75BBE1738105" @@ -184,7 +184,7 @@ async def test_async_step_user_takes_precedence_over_discovery(hass): user_input={"address": "61DE521B-F0BF-9F44-64D4-75BBE1738105"}, ) assert result2["type"] == FlowResultType.CREATE_ENTRY - assert result2["title"] == "IBS-TH 75BBE1738105" + assert result2["title"] == "IBS-TH 8105" assert result2["data"] == {} assert result2["result"].unique_id == "61DE521B-F0BF-9F44-64D4-75BBE1738105" diff --git a/tests/components/inkbird/test_sensor.py b/tests/components/inkbird/test_sensor.py index cafc22911c3..c54c6e3c242 100644 --- a/tests/components/inkbird/test_sensor.py +++ b/tests/components/inkbird/test_sensor.py @@ -39,10 +39,10 @@ async def test_sensors(hass): await hass.async_block_till_done() assert len(hass.states.async_all()) == 3 - temp_sensor = hass.states.get("sensor.ibs_th_75bbe1738105_battery") + temp_sensor = hass.states.get("sensor.ibs_th_8105_battery") temp_sensor_attribtes = temp_sensor.attributes assert temp_sensor.state == "87" - assert temp_sensor_attribtes[ATTR_FRIENDLY_NAME] == "IBS-TH 75BBE1738105 Battery" + assert temp_sensor_attribtes[ATTR_FRIENDLY_NAME] == "IBS-TH 8105 Battery" assert temp_sensor_attribtes[ATTR_UNIT_OF_MEASUREMENT] == "%" assert temp_sensor_attribtes[ATTR_STATE_CLASS] == "measurement" diff --git a/tests/components/lifx/test_config_flow.py b/tests/components/lifx/test_config_flow.py index f007e9ee0e8..05bf29f43e5 100644 --- a/tests/components/lifx/test_config_flow.py +++ b/tests/components/lifx/test_config_flow.py @@ -466,21 +466,38 @@ async def test_discovered_by_dhcp_or_discovery_failed_to_get_device(hass, source assert result["reason"] == "cannot_connect" -async def test_discovered_by_dhcp_updates_ip(hass): +@pytest.mark.parametrize( + "source, data", + [ + ( + config_entries.SOURCE_DHCP, + dhcp.DhcpServiceInfo(ip=IP_ADDRESS, macaddress=MAC_ADDRESS, hostname=LABEL), + ), + ( + config_entries.SOURCE_HOMEKIT, + zeroconf.ZeroconfServiceInfo( + host=IP_ADDRESS, + addresses=[IP_ADDRESS], + hostname=LABEL, + name=LABEL, + port=None, + properties={zeroconf.ATTR_PROPERTIES_ID: "any"}, + type="mock_type", + ), + ), + ], +) +async def test_discovered_by_dhcp_or_homekit_updates_ip(hass, source, data): """Update host from dhcp.""" config_entry = MockConfigEntry( domain=DOMAIN, data={CONF_HOST: "127.0.0.2"}, unique_id=SERIAL ) config_entry.add_to_hass(hass) - with _patch_discovery(no_device=True), _patch_config_flow_try_connect( - no_device=True - ): + with _patch_discovery(), _patch_config_flow_try_connect(): result = await hass.config_entries.flow.async_init( DOMAIN, - context={"source": config_entries.SOURCE_DHCP}, - data=dhcp.DhcpServiceInfo( - ip=IP_ADDRESS, macaddress=MAC_ADDRESS, hostname=LABEL - ), + context={"source": source}, + data=data, ) await hass.async_block_till_done() assert result["type"] == RESULT_TYPE_ABORT diff --git a/tests/components/system_bridge/test_config_flow.py b/tests/components/system_bridge/test_config_flow.py index 45131353550..d01ed9a3ff8 100644 --- a/tests/components/system_bridge/test_config_flow.py +++ b/tests/components/system_bridge/test_config_flow.py @@ -2,21 +2,14 @@ import asyncio from unittest.mock import patch -from systembridgeconnector.const import ( - EVENT_DATA, - EVENT_MESSAGE, - EVENT_MODULE, - EVENT_SUBTYPE, - EVENT_TYPE, - SUBTYPE_BAD_API_KEY, - TYPE_DATA_UPDATE, - TYPE_ERROR, -) +from systembridgeconnector.const import MODEL_SYSTEM, TYPE_DATA_UPDATE from systembridgeconnector.exceptions import ( AuthenticationException, ConnectionClosedException, ConnectionErrorException, ) +from systembridgeconnector.models.response import Response +from systembridgeconnector.models.system import LastUpdated, System from homeassistant import config_entries, data_entry_flow from homeassistant.components import zeroconf @@ -48,8 +41,8 @@ FIXTURE_ZEROCONF = zeroconf.ZeroconfServiceInfo( addresses=["1.1.1.1"], port=9170, hostname="test-bridge.local.", - type="_system-bridge._udp.local.", - name="System Bridge - test-bridge._system-bridge._udp.local.", + type="_system-bridge._tcp.local.", + name="System Bridge - test-bridge._system-bridge._tcp.local.", properties={ "address": "http://test-bridge:9170", "fqdn": "test-bridge", @@ -66,34 +59,70 @@ FIXTURE_ZEROCONF_BAD = zeroconf.ZeroconfServiceInfo( addresses=["1.1.1.1"], port=9170, hostname="test-bridge.local.", - type="_system-bridge._udp.local.", - name="System Bridge - test-bridge._system-bridge._udp.local.", + type="_system-bridge._tcp.local.", + name="System Bridge - test-bridge._system-bridge._tcp.local.", properties={ "something": "bad", }, ) -FIXTURE_DATA_SYSTEM = { - EVENT_TYPE: TYPE_DATA_UPDATE, - EVENT_MESSAGE: "Data changed", - EVENT_MODULE: "system", - EVENT_DATA: { - "uuid": FIXTURE_UUID, - }, -} -FIXTURE_DATA_SYSTEM_BAD = { - EVENT_TYPE: TYPE_DATA_UPDATE, - EVENT_MESSAGE: "Data changed", - EVENT_MODULE: "system", - EVENT_DATA: {}, -} +FIXTURE_SYSTEM = System( + id=FIXTURE_UUID, + boot_time=1, + fqdn="", + hostname="1.1.1.1", + ip_address_4="1.1.1.1", + mac_address=FIXTURE_MAC_ADDRESS, + platform="", + platform_version="", + uptime=1, + uuid=FIXTURE_UUID, + version="", + version_latest="", + version_newer_available=False, + last_updated=LastUpdated( + boot_time=1, + fqdn=1, + hostname=1, + ip_address_4=1, + mac_address=1, + platform=1, + platform_version=1, + uptime=1, + uuid=1, + version=1, + version_latest=1, + version_newer_available=1, + ), +) -FIXTURE_DATA_AUTH_ERROR = { - EVENT_TYPE: TYPE_ERROR, - EVENT_SUBTYPE: SUBTYPE_BAD_API_KEY, - EVENT_MESSAGE: "Invalid api-key", -} +FIXTURE_DATA_RESPONSE = Response( + id="1234", + type=TYPE_DATA_UPDATE, + subtype=None, + message="Data received", + module=MODEL_SYSTEM, + data=FIXTURE_SYSTEM, +) + +FIXTURE_DATA_RESPONSE_BAD = Response( + id="1234", + type=TYPE_DATA_UPDATE, + subtype=None, + message="Data received", + module=MODEL_SYSTEM, + data={}, +) + +FIXTURE_DATA_RESPONSE_BAD = Response( + id="1234", + type=TYPE_DATA_UPDATE, + subtype=None, + message="Data received", + module=MODEL_SYSTEM, + data={}, +) async def test_show_user_form(hass: HomeAssistant) -> None: @@ -117,9 +146,11 @@ async def test_user_flow(hass: HomeAssistant) -> None: with patch( "homeassistant.components.system_bridge.config_flow.WebSocketClient.connect" - ), patch("systembridgeconnector.websocket_client.WebSocketClient.get_data"), patch( - "systembridgeconnector.websocket_client.WebSocketClient.receive_message", - return_value=FIXTURE_DATA_SYSTEM, + ), patch( + "systembridgeconnector.websocket_client.WebSocketClient.get_data", + return_value=FIXTURE_DATA_RESPONSE, + ), patch( + "systembridgeconnector.websocket_client.WebSocketClient.listen" ), patch( "homeassistant.components.system_bridge.async_setup_entry", return_value=True, @@ -167,11 +198,13 @@ async def test_form_connection_closed_cannot_connect(hass: HomeAssistant) -> Non assert result["type"] == data_entry_flow.FlowResultType.FORM assert result["errors"] is None - with patch("systembridgeconnector.websocket_client.WebSocketClient.connect"), patch( - "systembridgeconnector.websocket_client.WebSocketClient.get_data" + with patch( + "homeassistant.components.system_bridge.config_flow.WebSocketClient.connect" ), patch( - "systembridgeconnector.websocket_client.WebSocketClient.receive_message", + "systembridgeconnector.websocket_client.WebSocketClient.get_data", side_effect=ConnectionClosedException, + ), patch( + "systembridgeconnector.websocket_client.WebSocketClient.listen", ): result2 = await hass.config_entries.flow.async_configure( result["flow_id"], FIXTURE_USER_INPUT @@ -192,11 +225,13 @@ async def test_form_timeout_cannot_connect(hass: HomeAssistant) -> None: assert result["type"] == data_entry_flow.FlowResultType.FORM assert result["errors"] is None - with patch("systembridgeconnector.websocket_client.WebSocketClient.connect"), patch( - "systembridgeconnector.websocket_client.WebSocketClient.get_data" + with patch( + "homeassistant.components.system_bridge.config_flow.WebSocketClient.connect" ), patch( - "systembridgeconnector.websocket_client.WebSocketClient.receive_message", + "systembridgeconnector.websocket_client.WebSocketClient.get_data", side_effect=asyncio.TimeoutError, + ), patch( + "systembridgeconnector.websocket_client.WebSocketClient.listen", ): result2 = await hass.config_entries.flow.async_configure( result["flow_id"], FIXTURE_USER_INPUT @@ -217,11 +252,13 @@ async def test_form_invalid_auth(hass: HomeAssistant) -> None: assert result["type"] == data_entry_flow.FlowResultType.FORM assert result["errors"] is None - with patch("systembridgeconnector.websocket_client.WebSocketClient.connect"), patch( - "systembridgeconnector.websocket_client.WebSocketClient.get_data" + with patch( + "homeassistant.components.system_bridge.config_flow.WebSocketClient.connect" ), patch( - "systembridgeconnector.websocket_client.WebSocketClient.receive_message", + "systembridgeconnector.websocket_client.WebSocketClient.get_data", side_effect=AuthenticationException, + ), patch( + "systembridgeconnector.websocket_client.WebSocketClient.listen", ): result2 = await hass.config_entries.flow.async_configure( result["flow_id"], FIXTURE_USER_INPUT @@ -242,11 +279,40 @@ async def test_form_uuid_error(hass: HomeAssistant) -> None: assert result["type"] == data_entry_flow.FlowResultType.FORM assert result["errors"] is None - with patch("systembridgeconnector.websocket_client.WebSocketClient.connect"), patch( - "systembridgeconnector.websocket_client.WebSocketClient.get_data" + with patch( + "homeassistant.components.system_bridge.config_flow.WebSocketClient.connect" ), patch( - "systembridgeconnector.websocket_client.WebSocketClient.receive_message", - return_value=FIXTURE_DATA_SYSTEM_BAD, + "systembridgeconnector.websocket_client.WebSocketClient.get_data", + side_effect=ValueError, + ), patch( + "systembridgeconnector.websocket_client.WebSocketClient.listen", + ): + result2 = await hass.config_entries.flow.async_configure( + result["flow_id"], FIXTURE_USER_INPUT + ) + await hass.async_block_till_done() + + assert result2["type"] == data_entry_flow.FlowResultType.FORM + assert result2["step_id"] == "user" + assert result2["errors"] == {"base": "cannot_connect"} + + +async def test_form_value_error(hass: HomeAssistant) -> None: + """Test we handle error from bad value.""" + result = await hass.config_entries.flow.async_init( + DOMAIN, context={"source": config_entries.SOURCE_USER} + ) + + assert result["type"] == data_entry_flow.FlowResultType.FORM + assert result["errors"] is None + + with patch( + "homeassistant.components.system_bridge.config_flow.WebSocketClient.connect" + ), patch( + "systembridgeconnector.websocket_client.WebSocketClient.get_data", + return_value=FIXTURE_DATA_RESPONSE_BAD, + ), patch( + "systembridgeconnector.websocket_client.WebSocketClient.listen", ): result2 = await hass.config_entries.flow.async_configure( result["flow_id"], FIXTURE_USER_INPUT @@ -267,11 +333,13 @@ async def test_form_unknown_error(hass: HomeAssistant) -> None: assert result["type"] == data_entry_flow.FlowResultType.FORM assert result["errors"] is None - with patch("systembridgeconnector.websocket_client.WebSocketClient.connect"), patch( - "systembridgeconnector.websocket_client.WebSocketClient.get_data" + with patch( + "homeassistant.components.system_bridge.config_flow.WebSocketClient.connect" ), patch( - "systembridgeconnector.websocket_client.WebSocketClient.receive_message", + "systembridgeconnector.websocket_client.WebSocketClient.get_data", side_effect=Exception, + ), patch( + "systembridgeconnector.websocket_client.WebSocketClient.listen", ): result2 = await hass.config_entries.flow.async_configure( result["flow_id"], FIXTURE_USER_INPUT @@ -292,11 +360,13 @@ async def test_reauth_authorization_error(hass: HomeAssistant) -> None: assert result["type"] == data_entry_flow.FlowResultType.FORM assert result["step_id"] == "authenticate" - with patch("systembridgeconnector.websocket_client.WebSocketClient.connect"), patch( - "systembridgeconnector.websocket_client.WebSocketClient.get_data" + with patch( + "homeassistant.components.system_bridge.config_flow.WebSocketClient.connect" ), patch( - "systembridgeconnector.websocket_client.WebSocketClient.receive_message", + "systembridgeconnector.websocket_client.WebSocketClient.get_data", side_effect=AuthenticationException, + ), patch( + "systembridgeconnector.websocket_client.WebSocketClient.listen", ): result2 = await hass.config_entries.flow.async_configure( result["flow_id"], FIXTURE_AUTH_INPUT @@ -340,11 +410,13 @@ async def test_reauth_connection_closed_error(hass: HomeAssistant) -> None: assert result["type"] == data_entry_flow.FlowResultType.FORM assert result["step_id"] == "authenticate" - with patch("systembridgeconnector.websocket_client.WebSocketClient.connect"), patch( - "systembridgeconnector.websocket_client.WebSocketClient.get_data" + with patch( + "homeassistant.components.system_bridge.config_flow.WebSocketClient.connect" ), patch( - "systembridgeconnector.websocket_client.WebSocketClient.receive_message", + "systembridgeconnector.websocket_client.WebSocketClient.get_data", side_effect=ConnectionClosedException, + ), patch( + "systembridgeconnector.websocket_client.WebSocketClient.listen", ): result2 = await hass.config_entries.flow.async_configure( result["flow_id"], FIXTURE_AUTH_INPUT @@ -370,11 +442,13 @@ async def test_reauth_flow(hass: HomeAssistant) -> None: assert result["type"] == data_entry_flow.FlowResultType.FORM assert result["step_id"] == "authenticate" - with patch("systembridgeconnector.websocket_client.WebSocketClient.connect"), patch( - "systembridgeconnector.websocket_client.WebSocketClient.get_data" + with patch( + "homeassistant.components.system_bridge.config_flow.WebSocketClient.connect" ), patch( - "systembridgeconnector.websocket_client.WebSocketClient.receive_message", - return_value=FIXTURE_DATA_SYSTEM, + "systembridgeconnector.websocket_client.WebSocketClient.get_data", + return_value=FIXTURE_DATA_RESPONSE, + ), patch( + "systembridgeconnector.websocket_client.WebSocketClient.listen" ), patch( "homeassistant.components.system_bridge.async_setup_entry", return_value=True, @@ -402,11 +476,13 @@ async def test_zeroconf_flow(hass: HomeAssistant) -> None: assert result["type"] == data_entry_flow.FlowResultType.FORM assert not result["errors"] - with patch("systembridgeconnector.websocket_client.WebSocketClient.connect"), patch( - "systembridgeconnector.websocket_client.WebSocketClient.get_data" + with patch( + "homeassistant.components.system_bridge.config_flow.WebSocketClient.connect" ), patch( - "systembridgeconnector.websocket_client.WebSocketClient.receive_message", - return_value=FIXTURE_DATA_SYSTEM, + "systembridgeconnector.websocket_client.WebSocketClient.get_data", + return_value=FIXTURE_DATA_RESPONSE, + ), patch( + "systembridgeconnector.websocket_client.WebSocketClient.listen" ), patch( "homeassistant.components.system_bridge.async_setup_entry", return_value=True,