From 0e7bf35e4a024b29339788509432770aa35a14fc Mon Sep 17 00:00:00 2001 From: Jc2k Date: Sat, 6 Aug 2022 21:45:44 +0100 Subject: [PATCH 01/11] Update gree to use the network component to set discovery interfaces (#75812) --- homeassistant/components/gree/__init__.py | 4 +++- homeassistant/components/gree/config_flow.py | 6 +++++- homeassistant/components/gree/manifest.json | 3 ++- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- tests/components/gree/common.py | 2 +- 6 files changed, 13 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/gree/__init__.py b/homeassistant/components/gree/__init__.py index d4a929f1642..ff3438ed53f 100644 --- a/homeassistant/components/gree/__init__.py +++ b/homeassistant/components/gree/__init__.py @@ -2,6 +2,7 @@ from datetime import timedelta import logging +from homeassistant.components.network import async_get_ipv4_broadcast_addresses from homeassistant.config_entries import ConfigEntry from homeassistant.const import Platform from homeassistant.core import HomeAssistant @@ -32,7 +33,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) async def _async_scan_update(_=None): - await gree_discovery.discovery.scan() + bcast_addr = list(await async_get_ipv4_broadcast_addresses(hass)) + await gree_discovery.discovery.scan(0, bcast_ifaces=bcast_addr) _LOGGER.debug("Scanning network for Gree devices") await _async_scan_update() diff --git a/homeassistant/components/gree/config_flow.py b/homeassistant/components/gree/config_flow.py index d317fe6d873..58f83cd4486 100644 --- a/homeassistant/components/gree/config_flow.py +++ b/homeassistant/components/gree/config_flow.py @@ -1,6 +1,7 @@ """Config flow for Gree.""" from greeclimate.discovery import Discovery +from homeassistant.components.network import async_get_ipv4_broadcast_addresses from homeassistant.core import HomeAssistant from homeassistant.helpers import config_entry_flow @@ -10,7 +11,10 @@ from .const import DISCOVERY_TIMEOUT, DOMAIN async def _async_has_devices(hass: HomeAssistant) -> bool: """Return if there are devices that can be discovered.""" gree_discovery = Discovery(DISCOVERY_TIMEOUT) - devices = await gree_discovery.scan(wait_for=DISCOVERY_TIMEOUT) + bcast_addr = list(await async_get_ipv4_broadcast_addresses(hass)) + devices = await gree_discovery.scan( + wait_for=DISCOVERY_TIMEOUT, bcast_ifaces=bcast_addr + ) return len(devices) > 0 diff --git a/homeassistant/components/gree/manifest.json b/homeassistant/components/gree/manifest.json index 1b2c8dd6a2a..97c0ec1780c 100644 --- a/homeassistant/components/gree/manifest.json +++ b/homeassistant/components/gree/manifest.json @@ -3,7 +3,8 @@ "name": "Gree Climate", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/gree", - "requirements": ["greeclimate==1.2.0"], + "requirements": ["greeclimate==1.3.0"], + "dependencies": ["network"], "codeowners": ["@cmroche"], "iot_class": "local_polling", "loggers": ["greeclimate"] diff --git a/requirements_all.txt b/requirements_all.txt index c6c9337cd7b..9e968a3cdb0 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -769,7 +769,7 @@ gpiozero==1.6.2 gps3==0.33.3 # homeassistant.components.gree -greeclimate==1.2.0 +greeclimate==1.3.0 # homeassistant.components.greeneye_monitor greeneye_monitor==3.0.3 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 210126d6f38..3482f9496c8 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -564,7 +564,7 @@ googlemaps==2.5.1 govee-ble==0.12.6 # homeassistant.components.gree -greeclimate==1.2.0 +greeclimate==1.3.0 # homeassistant.components.greeneye_monitor greeneye_monitor==3.0.3 diff --git a/tests/components/gree/common.py b/tests/components/gree/common.py index c7db03b118f..cd8a2d6ee28 100644 --- a/tests/components/gree/common.py +++ b/tests/components/gree/common.py @@ -28,7 +28,7 @@ class FakeDiscovery: """Add an event listener.""" self._listeners.append(listener) - async def scan(self, wait_for: int = 0): + async def scan(self, wait_for: int = 0, bcast_ifaces=None): """Search for devices, return mocked data.""" self.scan_count += 1 _LOGGER.info("CALLED SCAN %d TIMES", self.scan_count) From 8bfc3525241e6a799bcd1b0b29927d90e12c8868 Mon Sep 17 00:00:00 2001 From: Joakim Plate Date: Fri, 5 Aug 2022 16:06:19 +0200 Subject: [PATCH 02/11] Use stored philips_js system data on start (#75981) Co-authored-by: Martin Hjelmare --- homeassistant/components/philips_js/__init__.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/homeassistant/components/philips_js/__init__.py b/homeassistant/components/philips_js/__init__.py index 9e574e69f90..24b3f9a91e0 100644 --- a/homeassistant/components/philips_js/__init__.py +++ b/homeassistant/components/philips_js/__init__.py @@ -38,15 +38,22 @@ LOGGER = logging.getLogger(__name__) async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Set up Philips TV from a config entry.""" + system: SystemType | None = entry.data.get(CONF_SYSTEM) tvapi = PhilipsTV( entry.data[CONF_HOST], entry.data[CONF_API_VERSION], username=entry.data.get(CONF_USERNAME), password=entry.data.get(CONF_PASSWORD), + system=system, ) coordinator = PhilipsTVDataUpdateCoordinator(hass, tvapi, entry.options) await coordinator.async_refresh() + + if (actual_system := tvapi.system) and actual_system != system: + data = {**entry.data, CONF_SYSTEM: actual_system} + hass.config_entries.async_update_entry(entry, data=data) + hass.data.setdefault(DOMAIN, {}) hass.data[DOMAIN][entry.entry_id] = coordinator From 9c21d565394cbc0d90b6dcab80c5f3ccae4f4592 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 7 Aug 2022 05:03:56 -1000 Subject: [PATCH 03/11] Ensure bluetooth recovers if Dbus gets restarted (#76249) --- .../components/bluetooth/__init__.py | 68 ++++++++++++++++--- tests/components/bluetooth/test_init.py | 56 +++++++++++++++ 2 files changed, 116 insertions(+), 8 deletions(-) diff --git a/homeassistant/components/bluetooth/__init__.py b/homeassistant/components/bluetooth/__init__.py index 0b81472f838..2d7b47b7552 100644 --- a/homeassistant/components/bluetooth/__init__.py +++ b/homeassistant/components/bluetooth/__init__.py @@ -8,6 +8,7 @@ from dataclasses import dataclass from datetime import datetime, timedelta from enum import Enum import logging +import time from typing import TYPE_CHECKING, Final import async_timeout @@ -56,6 +57,10 @@ START_TIMEOUT = 9 SOURCE_LOCAL: Final = "local" +SCANNER_WATCHDOG_TIMEOUT: Final = 60 * 5 +SCANNER_WATCHDOG_INTERVAL: Final = timedelta(seconds=SCANNER_WATCHDOG_TIMEOUT) +MONOTONIC_TIME = time.monotonic + @dataclass class BluetoothServiceInfoBleak(BluetoothServiceInfo): @@ -252,9 +257,10 @@ async def async_setup_entry( ) -> bool: """Set up the bluetooth integration from a config entry.""" manager: BluetoothManager = hass.data[DOMAIN] - await manager.async_start( - BluetoothScanningMode.ACTIVE, entry.options.get(CONF_ADAPTER) - ) + async with manager.start_stop_lock: + await manager.async_start( + BluetoothScanningMode.ACTIVE, entry.options.get(CONF_ADAPTER) + ) entry.async_on_unload(entry.add_update_listener(_async_update_listener)) return True @@ -263,8 +269,6 @@ async def _async_update_listener( hass: HomeAssistant, entry: config_entries.ConfigEntry ) -> None: """Handle options update.""" - manager: BluetoothManager = hass.data[DOMAIN] - manager.async_start_reload() await hass.config_entries.async_reload(entry.entry_id) @@ -273,7 +277,9 @@ async def async_unload_entry( ) -> bool: """Unload a config entry.""" manager: BluetoothManager = hass.data[DOMAIN] - await manager.async_stop() + async with manager.start_stop_lock: + manager.async_start_reload() + await manager.async_stop() return True @@ -289,13 +295,19 @@ class BluetoothManager: self.hass = hass self._integration_matcher = integration_matcher self.scanner: HaBleakScanner | None = None + self.start_stop_lock = asyncio.Lock() self._cancel_device_detected: CALLBACK_TYPE | None = None self._cancel_unavailable_tracking: CALLBACK_TYPE | None = None + self._cancel_stop: CALLBACK_TYPE | None = None + self._cancel_watchdog: CALLBACK_TYPE | None = None self._unavailable_callbacks: dict[str, list[Callable[[str], None]]] = {} self._callbacks: list[ tuple[BluetoothCallback, BluetoothCallbackMatcher | None] ] = [] + self._last_detection = 0.0 self._reloading = False + self._adapter: str | None = None + self._scanning_mode = BluetoothScanningMode.ACTIVE @hass_callback def async_setup(self) -> None: @@ -317,6 +329,8 @@ class BluetoothManager: ) -> None: """Set up BT Discovery.""" assert self.scanner is not None + self._adapter = adapter + self._scanning_mode = scanning_mode if self._reloading: # On reload, we need to reset the scanner instance # since the devices in its history may not be reachable @@ -381,7 +395,32 @@ class BluetoothManager: _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() - self.hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, self.async_stop) + self._async_setup_scanner_watchdog() + self._cancel_stop = self.hass.bus.async_listen_once( + EVENT_HOMEASSISTANT_STOP, self._async_hass_stopping + ) + + @hass_callback + def _async_setup_scanner_watchdog(self) -> None: + """If Dbus gets restarted or updated, we need to restart the scanner.""" + self._last_detection = MONOTONIC_TIME() + self._cancel_watchdog = async_track_time_interval( + self.hass, self._async_scanner_watchdog, SCANNER_WATCHDOG_INTERVAL + ) + + async def _async_scanner_watchdog(self, now: datetime) -> None: + """Check if the scanner is running.""" + time_since_last_detection = MONOTONIC_TIME() - self._last_detection + if time_since_last_detection < SCANNER_WATCHDOG_TIMEOUT: + return + _LOGGER.info( + "Bluetooth scanner has gone quiet for %s, restarting", + SCANNER_WATCHDOG_INTERVAL, + ) + async with self.start_stop_lock: + self.async_start_reload() + await self.async_stop() + await self.async_start(self._scanning_mode, self._adapter) @hass_callback def async_setup_unavailable_tracking(self) -> None: @@ -416,6 +455,7 @@ class BluetoothManager: self, device: BLEDevice, advertisement_data: AdvertisementData ) -> None: """Handle a detected device.""" + self._last_detection = MONOTONIC_TIME() matched_domains = self._integration_matcher.match_domains( device, advertisement_data ) @@ -528,14 +568,26 @@ class BluetoothManager: for device_adv in self.scanner.history.values() ] - async def async_stop(self, event: Event | None = None) -> None: + async def _async_hass_stopping(self, event: Event) -> None: + """Stop the Bluetooth integration at shutdown.""" + self._cancel_stop = None + await self.async_stop() + + 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 if self._cancel_unavailable_tracking: self._cancel_unavailable_tracking() self._cancel_unavailable_tracking = None + if self._cancel_stop: + self._cancel_stop() + self._cancel_stop = None if self.scanner: try: await self.scanner.stop() # type: ignore[no-untyped-call] diff --git a/tests/components/bluetooth/test_init.py b/tests/components/bluetooth/test_init.py index ba315b1f380..9432be9f2e4 100644 --- a/tests/components/bluetooth/test_init.py +++ b/tests/components/bluetooth/test_init.py @@ -10,6 +10,8 @@ import pytest from homeassistant.components import bluetooth from homeassistant.components.bluetooth import ( + SCANNER_WATCHDOG_INTERVAL, + SCANNER_WATCHDOG_TIMEOUT, SOURCE_LOCAL, UNAVAILABLE_TRACK_SECONDS, BluetoothChange, @@ -1522,3 +1524,57 @@ async def test_invalid_dbus_message(hass, caplog): hass.bus.async_fire(EVENT_HOMEASSISTANT_STOP) await hass.async_block_till_done() assert "dbus" in caplog.text + + +async def test_recovery_from_dbus_restart( + hass, mock_bleak_scanner_start, enable_bluetooth +): + """Test we can recover when DBus gets restarted out from under us.""" + assert await async_setup_component(hass, bluetooth.DOMAIN, {bluetooth.DOMAIN: {}}) + await hass.async_block_till_done() + assert len(mock_bleak_scanner_start.mock_calls) == 1 + + start_time_monotonic = 1000 + scanner = _get_underlying_scanner() + mock_discovered = [MagicMock()] + type(scanner).discovered_devices = mock_discovered + + # Ensure we don't restart the scanner if we don't need to + with patch( + "homeassistant.components.bluetooth.MONOTONIC_TIME", + return_value=start_time_monotonic + 10, + ): + async_fire_time_changed(hass, dt_util.utcnow() + SCANNER_WATCHDOG_INTERVAL) + await hass.async_block_till_done() + + assert len(mock_bleak_scanner_start.mock_calls) == 1 + + # Fire a callback to reset the timer + with patch( + "homeassistant.components.bluetooth.MONOTONIC_TIME", + return_value=start_time_monotonic, + ): + scanner._callback( + BLEDevice("44:44:33:11:23:42", "any_name"), + AdvertisementData(local_name="any_name"), + ) + + # Ensure we don't restart the scanner if we don't need to + with patch( + "homeassistant.components.bluetooth.MONOTONIC_TIME", + return_value=start_time_monotonic + 20, + ): + async_fire_time_changed(hass, dt_util.utcnow() + SCANNER_WATCHDOG_INTERVAL) + await hass.async_block_till_done() + + assert len(mock_bleak_scanner_start.mock_calls) == 1 + + # We hit the timer, so we restart the scanner + with patch( + "homeassistant.components.bluetooth.MONOTONIC_TIME", + return_value=start_time_monotonic + SCANNER_WATCHDOG_TIMEOUT, + ): + async_fire_time_changed(hass, dt_util.utcnow() + SCANNER_WATCHDOG_INTERVAL) + await hass.async_block_till_done() + + assert len(mock_bleak_scanner_start.mock_calls) == 2 From bfa64d2e01521315e47aa2ae3b713cd9677d6a2d Mon Sep 17 00:00:00 2001 From: Maciej Bieniek Date: Sun, 7 Aug 2022 15:04:04 +0200 Subject: [PATCH 04/11] Fix default sensor names in NextDNS integration (#76264) --- homeassistant/components/nextdns/sensor.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/nextdns/sensor.py b/homeassistant/components/nextdns/sensor.py index 168c0be8cd0..422bc2a237b 100644 --- a/homeassistant/components/nextdns/sensor.py +++ b/homeassistant/components/nextdns/sensor.py @@ -135,7 +135,7 @@ SENSORS: tuple[NextDnsSensorEntityDescription, ...] = ( entity_category=EntityCategory.DIAGNOSTIC, entity_registry_enabled_default=False, icon="mdi:dns", - name="TCP Queries", + name="TCP queries", native_unit_of_measurement="queries", state_class=SensorStateClass.TOTAL, value=lambda data: data.tcp_queries, @@ -190,7 +190,7 @@ SENSORS: tuple[NextDnsSensorEntityDescription, ...] = ( entity_category=EntityCategory.DIAGNOSTIC, entity_registry_enabled_default=False, icon="mdi:dns", - name="TCP Queries Ratio", + name="TCP queries ratio", native_unit_of_measurement=PERCENTAGE, state_class=SensorStateClass.MEASUREMENT, value=lambda data: data.tcp_queries_ratio, From 8971a2073ed603e7bccf655344220a21bc0e442e Mon Sep 17 00:00:00 2001 From: puddly <32534428+puddly@users.noreply.github.com> Date: Fri, 5 Aug 2022 05:06:40 -0400 Subject: [PATCH 05/11] Bump ZHA dependencies (#76275) --- homeassistant/components/zha/manifest.json | 6 +++--- requirements_all.txt | 6 +++--- requirements_test_all.txt | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/homeassistant/components/zha/manifest.json b/homeassistant/components/zha/manifest.json index 179302af1cd..bad84054f1f 100644 --- a/homeassistant/components/zha/manifest.json +++ b/homeassistant/components/zha/manifest.json @@ -4,14 +4,14 @@ "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/zha", "requirements": [ - "bellows==0.31.2", + "bellows==0.31.3", "pyserial==3.5", "pyserial-asyncio==0.6", "zha-quirks==0.0.78", "zigpy-deconz==0.18.0", - "zigpy==0.48.0", + "zigpy==0.49.0", "zigpy-xbee==0.15.0", - "zigpy-zigate==0.9.0", + "zigpy-zigate==0.9.1", "zigpy-znp==0.8.1" ], "usb": [ diff --git a/requirements_all.txt b/requirements_all.txt index 9e968a3cdb0..df989f287b9 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -396,7 +396,7 @@ beautifulsoup4==4.11.1 # beewi_smartclim==0.0.10 # homeassistant.components.zha -bellows==0.31.2 +bellows==0.31.3 # homeassistant.components.bmw_connected_drive bimmer_connected==0.10.1 @@ -2529,13 +2529,13 @@ zigpy-deconz==0.18.0 zigpy-xbee==0.15.0 # homeassistant.components.zha -zigpy-zigate==0.9.0 +zigpy-zigate==0.9.1 # homeassistant.components.zha zigpy-znp==0.8.1 # homeassistant.components.zha -zigpy==0.48.0 +zigpy==0.49.0 # homeassistant.components.zoneminder zm-py==0.5.2 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 3482f9496c8..344cd8d5675 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -320,7 +320,7 @@ base36==0.1.1 beautifulsoup4==4.11.1 # homeassistant.components.zha -bellows==0.31.2 +bellows==0.31.3 # homeassistant.components.bmw_connected_drive bimmer_connected==0.10.1 @@ -1703,13 +1703,13 @@ zigpy-deconz==0.18.0 zigpy-xbee==0.15.0 # homeassistant.components.zha -zigpy-zigate==0.9.0 +zigpy-zigate==0.9.1 # homeassistant.components.zha zigpy-znp==0.8.1 # homeassistant.components.zha -zigpy==0.48.0 +zigpy==0.49.0 # homeassistant.components.zwave_js zwave-js-server-python==0.39.0 From 9cf11cf6ed0e2645da0b82f843827944397030b4 Mon Sep 17 00:00:00 2001 From: Robert Svensson Date: Fri, 5 Aug 2022 11:22:55 +0200 Subject: [PATCH 06/11] Bump pydeconz to v102 (#76287) --- homeassistant/components/deconz/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/deconz/manifest.json b/homeassistant/components/deconz/manifest.json index 6384ebfcd5f..e4e412056e6 100644 --- a/homeassistant/components/deconz/manifest.json +++ b/homeassistant/components/deconz/manifest.json @@ -3,7 +3,7 @@ "name": "deCONZ", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/deconz", - "requirements": ["pydeconz==101"], + "requirements": ["pydeconz==102"], "ssdp": [ { "manufacturer": "Royal Philips Electronics", diff --git a/requirements_all.txt b/requirements_all.txt index df989f287b9..e0e7f26c4b1 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1455,7 +1455,7 @@ pydaikin==2.7.0 pydanfossair==0.1.0 # homeassistant.components.deconz -pydeconz==101 +pydeconz==102 # homeassistant.components.delijn pydelijn==1.0.0 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 344cd8d5675..a58d5994737 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1001,7 +1001,7 @@ pycoolmasternet-async==0.1.2 pydaikin==2.7.0 # homeassistant.components.deconz -pydeconz==101 +pydeconz==102 # homeassistant.components.dexcom pydexcom==0.2.3 From 1c2dd78e4cfe1f0d17062768c9346e4feb4b9879 Mon Sep 17 00:00:00 2001 From: "David F. Mulcahey" Date: Fri, 5 Aug 2022 09:34:21 -0400 Subject: [PATCH 07/11] Fix ZHA light color temp support (#76305) --- .../components/zha/core/channels/lighting.py | 39 +++++++------------ 1 file changed, 14 insertions(+), 25 deletions(-) diff --git a/homeassistant/components/zha/core/channels/lighting.py b/homeassistant/components/zha/core/channels/lighting.py index 36bb0beb17d..1754b9aff68 100644 --- a/homeassistant/components/zha/core/channels/lighting.py +++ b/homeassistant/components/zha/core/channels/lighting.py @@ -1,7 +1,7 @@ """Lighting channels module for Zigbee Home Automation.""" from __future__ import annotations -from contextlib import suppress +from functools import cached_property from zigpy.zcl.clusters import lighting @@ -46,17 +46,8 @@ class ColorChannel(ZigbeeChannel): "color_loop_active": False, } - @property - def color_capabilities(self) -> int: - """Return color capabilities of the light.""" - with suppress(KeyError): - return self.cluster["color_capabilities"] - if self.cluster.get("color_temperature") is not None: - return self.CAPABILITIES_COLOR_XY | self.CAPABILITIES_COLOR_TEMP - return self.CAPABILITIES_COLOR_XY - - @property - def zcl_color_capabilities(self) -> lighting.Color.ColorCapabilities: + @cached_property + def color_capabilities(self) -> lighting.Color.ColorCapabilities: """Return ZCL color capabilities of the light.""" color_capabilities = self.cluster.get("color_capabilities") if color_capabilities is None: @@ -117,43 +108,41 @@ class ColorChannel(ZigbeeChannel): def hs_supported(self) -> bool: """Return True if the channel supports hue and saturation.""" return ( - self.zcl_color_capabilities is not None + self.color_capabilities is not None and lighting.Color.ColorCapabilities.Hue_and_saturation - in self.zcl_color_capabilities + in self.color_capabilities ) @property def enhanced_hue_supported(self) -> bool: """Return True if the channel supports enhanced hue and saturation.""" return ( - self.zcl_color_capabilities is not None - and lighting.Color.ColorCapabilities.Enhanced_hue - in self.zcl_color_capabilities + self.color_capabilities is not None + and lighting.Color.ColorCapabilities.Enhanced_hue in self.color_capabilities ) @property def xy_supported(self) -> bool: """Return True if the channel supports xy.""" return ( - self.zcl_color_capabilities is not None + self.color_capabilities is not None and lighting.Color.ColorCapabilities.XY_attributes - in self.zcl_color_capabilities + in self.color_capabilities ) @property def color_temp_supported(self) -> bool: """Return True if the channel supports color temperature.""" return ( - self.zcl_color_capabilities is not None + self.color_capabilities is not None and lighting.Color.ColorCapabilities.Color_temperature - in self.zcl_color_capabilities - ) + in self.color_capabilities + ) or self.color_temperature is not None @property def color_loop_supported(self) -> bool: """Return True if the channel supports color loop.""" return ( - self.zcl_color_capabilities is not None - and lighting.Color.ColorCapabilities.Color_loop - in self.zcl_color_capabilities + self.color_capabilities is not None + and lighting.Color.ColorCapabilities.Color_loop in self.color_capabilities ) From 4b63aa7f15b34ed8d03053f9b73ff0dd6f5cd0f5 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 6 Aug 2022 00:46:27 -1000 Subject: [PATCH 08/11] Bump pySwitchbot to 0.18.4 (#76322) * Bump pySwitchbot to 0.18.3 Fixes #76321 Changelog: https://github.com/Danielhiversen/pySwitchbot/compare/0.17.3...0.18.3 * bump --- homeassistant/components/switchbot/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/switchbot/manifest.json b/homeassistant/components/switchbot/manifest.json index f01eae4a938..b413b44d605 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.17.3"], + "requirements": ["PySwitchbot==0.18.4"], "config_flow": true, "dependencies": ["bluetooth"], "codeowners": [ diff --git a/requirements_all.txt b/requirements_all.txt index e0e7f26c4b1..106fb703461 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.17.3 +PySwitchbot==0.18.4 # homeassistant.components.transport_nsw PyTransportNSW==0.1.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index a58d5994737..c937ab13612 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.17.3 +PySwitchbot==0.18.4 # homeassistant.components.transport_nsw PyTransportNSW==0.1.1 From 5026bff4264d82c8c50c7c7414779a5947e7d3ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Roy?= Date: Fri, 5 Aug 2022 17:30:45 -0700 Subject: [PATCH 09/11] Bump aiobafi6 to 0.7.2 to unblock #76328 (#76330) --- homeassistant/components/baf/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/baf/manifest.json b/homeassistant/components/baf/manifest.json index 15e0272b2b0..7462a64e770 100644 --- a/homeassistant/components/baf/manifest.json +++ b/homeassistant/components/baf/manifest.json @@ -3,7 +3,7 @@ "name": "Big Ass Fans", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/baf", - "requirements": ["aiobafi6==0.7.0"], + "requirements": ["aiobafi6==0.7.2"], "codeowners": ["@bdraco", "@jfroy"], "iot_class": "local_push", "zeroconf": [ diff --git a/requirements_all.txt b/requirements_all.txt index 106fb703461..5bd396ea124 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -128,7 +128,7 @@ aioasuswrt==1.4.0 aioazuredevops==1.3.5 # homeassistant.components.baf -aiobafi6==0.7.0 +aiobafi6==0.7.2 # homeassistant.components.aws aiobotocore==2.1.0 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index c937ab13612..86b7dbb93e6 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -115,7 +115,7 @@ aioasuswrt==1.4.0 aioazuredevops==1.3.5 # homeassistant.components.baf -aiobafi6==0.7.0 +aiobafi6==0.7.2 # homeassistant.components.aws aiobotocore==2.1.0 From e96903fddf03859676e38b0769bb2db68b3de057 Mon Sep 17 00:00:00 2001 From: Joakim Plate Date: Sun, 7 Aug 2022 15:42:47 +0200 Subject: [PATCH 10/11] Postpone broadlink platform switch until config entry is ready (#76371) --- homeassistant/components/broadlink/switch.py | 24 +++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/homeassistant/components/broadlink/switch.py b/homeassistant/components/broadlink/switch.py index 6a015748bd0..d38898a513f 100644 --- a/homeassistant/components/broadlink/switch.py +++ b/homeassistant/components/broadlink/switch.py @@ -26,11 +26,13 @@ from homeassistant.const import ( Platform, ) from homeassistant.core import HomeAssistant +from homeassistant.exceptions import PlatformNotReady import homeassistant.helpers.config_validation as cv from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.restore_state import RestoreEntity from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType +from . import BroadlinkDevice from .const import DOMAIN from .entity import BroadlinkEntity from .helpers import data_packet, import_device, mac_address @@ -80,8 +82,18 @@ async def async_setup_platform( host = config.get(CONF_HOST) if switches := config.get(CONF_SWITCHES): - platform_data = hass.data[DOMAIN].platforms.setdefault(Platform.SWITCH, {}) - platform_data.setdefault(mac_addr, []).extend(switches) + platform_data = hass.data[DOMAIN].platforms.get(Platform.SWITCH, {}) + async_add_entities_config_entry: AddEntitiesCallback + device: BroadlinkDevice + async_add_entities_config_entry, device = platform_data.get( + mac_addr, (None, None) + ) + if not async_add_entities_config_entry: + raise PlatformNotReady + + async_add_entities_config_entry( + BroadlinkRMSwitch(device, config) for config in switches + ) else: _LOGGER.warning( @@ -104,12 +116,8 @@ async def async_setup_entry( switches: list[BroadlinkSwitch] = [] if device.api.type in {"RM4MINI", "RM4PRO", "RMMINI", "RMMINIB", "RMPRO"}: - platform_data = hass.data[DOMAIN].platforms.get(Platform.SWITCH, {}) - user_defined_switches = platform_data.get(device.api.mac, {}) - switches.extend( - BroadlinkRMSwitch(device, config) for config in user_defined_switches - ) - + platform_data = hass.data[DOMAIN].platforms.setdefault(Platform.SWITCH, {}) + platform_data[device.api.mac] = async_add_entities, device elif device.api.type == "SP1": switches.append(BroadlinkSP1Switch(device)) From c9581f6a2eb99416a2c4aeb7fb2a1d4e5c3837f6 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sun, 7 Aug 2022 12:13:08 -0400 Subject: [PATCH 11/11] Bumped version to 2022.8.2 --- homeassistant/const.py | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/const.py b/homeassistant/const.py index b08400c0cd5..dda81cbdc5c 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 = "1" +PATCH_VERSION: Final = "2" __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 59ebe40572d..568607d6d0d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "homeassistant" -version = "2022.8.1" +version = "2022.8.2" license = {text = "Apache-2.0"} description = "Open-source home automation platform running on Python 3." readme = "README.rst"