From 5ab7c8e9bab6f8cc9a18d461db065bc9e689ad2c Mon Sep 17 00:00:00 2001 From: Daan Beverdam Date: Thu, 17 Nov 2022 21:57:26 +0100 Subject: [PATCH 01/13] Fix moving average for 0 values (#80476) --- homeassistant/components/filter/sensor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/filter/sensor.py b/homeassistant/components/filter/sensor.py index 4c9c83a8787..ce70ed14d19 100644 --- a/homeassistant/components/filter/sensor.py +++ b/homeassistant/components/filter/sensor.py @@ -612,7 +612,7 @@ class TimeSMAFilter(Filter, SensorEntity): moving_sum = 0 start = new_state.timestamp - self._time_window - prev_state = self.last_leak or self.queue[0] + prev_state = self.last_leak if self.last_leak is not None else self.queue[0] for state in self.queue: moving_sum += (state.timestamp - start).total_seconds() * prev_state.state start = state.timestamp From 6a73406e9f5857c7d263e2d78959c0f7d3b5052a Mon Sep 17 00:00:00 2001 From: jan iversen Date: Fri, 18 Nov 2022 09:32:51 +0100 Subject: [PATCH 02/13] Solve Modbus reload issue (#82253) fixes undefined --- homeassistant/components/modbus/__init__.py | 1 - homeassistant/components/modbus/modbus.py | 6 ++++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/modbus/__init__.py b/homeassistant/components/modbus/__init__.py index 8aa2903506f..ec04d5f147d 100644 --- a/homeassistant/components/modbus/__init__.py +++ b/homeassistant/components/modbus/__init__.py @@ -375,4 +375,3 @@ async def async_reset_platform(hass: HomeAssistant, integration_name: str) -> No hubs = hass.data[DOMAIN] for name in hubs: await hubs[name].async_close() - del hass.data[DOMAIN] diff --git a/homeassistant/components/modbus/modbus.py b/homeassistant/components/modbus/modbus.py index 5e15f65035a..e2240f530c6 100644 --- a/homeassistant/components/modbus/modbus.py +++ b/homeassistant/components/modbus/modbus.py @@ -132,6 +132,12 @@ async def async_modbus_setup( await async_setup_reload_service(hass, DOMAIN, [DOMAIN]) + if DOMAIN in hass.data and config[DOMAIN] == []: + hubs = hass.data[DOMAIN] + for name in hubs: + if not await hubs[name].async_setup(): + return False + hass.data[DOMAIN] = hub_collect = {} for conf_hub in config[DOMAIN]: my_hub = ModbusHub(hass, conf_hub) From 1c06c6c1e6d3d9dd23c72256c7a067f29deadd40 Mon Sep 17 00:00:00 2001 From: Joakim Plate Date: Fri, 18 Nov 2022 09:56:34 +0100 Subject: [PATCH 03/13] Add kilo watts unit mapping for nibe_heatpump (#82284) --- homeassistant/components/nibe_heatpump/sensor.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/homeassistant/components/nibe_heatpump/sensor.py b/homeassistant/components/nibe_heatpump/sensor.py index 66c66aaabe1..0b12afd9e05 100644 --- a/homeassistant/components/nibe_heatpump/sensor.py +++ b/homeassistant/components/nibe_heatpump/sensor.py @@ -19,6 +19,7 @@ from homeassistant.const import ( ENERGY_KILO_WATT_HOUR, ENERGY_MEGA_WATT_HOUR, ENERGY_WATT_HOUR, + POWER_KILO_WATT, POWER_WATT, TEMP_CELSIUS, TEMP_FAHRENHEIT, @@ -80,6 +81,13 @@ UNIT_DESCRIPTIONS = { state_class=SensorStateClass.MEASUREMENT, native_unit_of_measurement=POWER_WATT, ), + "kW": SensorEntityDescription( + key="kW", + entity_category=EntityCategory.DIAGNOSTIC, + device_class=SensorDeviceClass.POWER, + state_class=SensorStateClass.MEASUREMENT, + native_unit_of_measurement=POWER_KILO_WATT, + ), "Wh": SensorEntityDescription( key="Wh", entity_category=EntityCategory.DIAGNOSTIC, From df2953403ed1604bb4da90d1fa9ba0fc155b12a2 Mon Sep 17 00:00:00 2001 From: Aaron Bach Date: Fri, 18 Nov 2022 17:37:12 -0700 Subject: [PATCH 04/13] Bump `regenmaschine` to 2022.11.0 (#82337) fixes undefined --- homeassistant/components/rainmachine/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/rainmachine/manifest.json b/homeassistant/components/rainmachine/manifest.json index a41db1d18f9..a8f6f316d3a 100644 --- a/homeassistant/components/rainmachine/manifest.json +++ b/homeassistant/components/rainmachine/manifest.json @@ -3,7 +3,7 @@ "name": "RainMachine", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/rainmachine", - "requirements": ["regenmaschine==2022.10.0"], + "requirements": ["regenmaschine==2022.11.0"], "codeowners": ["@bachya"], "iot_class": "local_polling", "homekit": { diff --git a/requirements_all.txt b/requirements_all.txt index bbe5c347870..cfd2b640142 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2153,7 +2153,7 @@ raincloudy==0.0.7 raspyrfm-client==1.2.8 # homeassistant.components.rainmachine -regenmaschine==2022.10.0 +regenmaschine==2022.11.0 # homeassistant.components.renault renault-api==0.1.11 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 1415f9b4cb6..d8aa5615e61 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1489,7 +1489,7 @@ radios==0.1.1 radiotherm==2.1.0 # homeassistant.components.rainmachine -regenmaschine==2022.10.0 +regenmaschine==2022.11.0 # homeassistant.components.renault renault-api==0.1.11 From 23280268c81b9e881ff5cfc0cddaf3534ab421a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Klomp?= Date: Sat, 19 Nov 2022 16:05:38 +0100 Subject: [PATCH 05/13] Bump pysma to version 0.7.3 (#82343) fixes undefined --- homeassistant/components/sma/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/sma/manifest.json b/homeassistant/components/sma/manifest.json index 83bf4258a95..f4e82a550e3 100644 --- a/homeassistant/components/sma/manifest.json +++ b/homeassistant/components/sma/manifest.json @@ -3,7 +3,7 @@ "name": "SMA Solar", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/sma", - "requirements": ["pysma==0.7.2"], + "requirements": ["pysma==0.7.3"], "codeowners": ["@kellerza", "@rklomp"], "iot_class": "local_polling", "loggers": ["pysma"] diff --git a/requirements_all.txt b/requirements_all.txt index cfd2b640142..f0be7b4d44c 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1893,7 +1893,7 @@ pysignalclirestapi==0.3.18 pyskyqhub==0.1.4 # homeassistant.components.sma -pysma==0.7.2 +pysma==0.7.3 # homeassistant.components.smappee pysmappee==0.2.29 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index d8aa5615e61..51e6f17d852 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1334,7 +1334,7 @@ pysiaalarm==3.0.2 pysignalclirestapi==0.3.18 # homeassistant.components.sma -pysma==0.7.2 +pysma==0.7.3 # homeassistant.components.smappee pysmappee==0.2.29 From f490119fed010f58d2f357620e2c0b61d1435981 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 19 Nov 2022 06:49:54 -0600 Subject: [PATCH 06/13] Bump flux_led to 0.28.34 (#82347) * Bump flux_led to 0.28.33 fixes #75832 changelog: https://github.com/Danielhiversen/flux_led/compare/0.28.32...0.28.33 * more more bump for legacy turn on --- homeassistant/components/flux_led/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/flux_led/manifest.json b/homeassistant/components/flux_led/manifest.json index 632ef04e456..66aa9fe0b92 100644 --- a/homeassistant/components/flux_led/manifest.json +++ b/homeassistant/components/flux_led/manifest.json @@ -4,7 +4,7 @@ "config_flow": true, "dependencies": ["network"], "documentation": "https://www.home-assistant.io/integrations/flux_led", - "requirements": ["flux_led==0.28.32"], + "requirements": ["flux_led==0.28.34"], "quality_scale": "platinum", "codeowners": ["@icemanch", "@bdraco"], "iot_class": "local_push", diff --git a/requirements_all.txt b/requirements_all.txt index f0be7b4d44c..2218f2d77a4 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -693,7 +693,7 @@ fjaraskupan==2.2.0 flipr-api==1.4.2 # homeassistant.components.flux_led -flux_led==0.28.32 +flux_led==0.28.34 # homeassistant.components.homekit # homeassistant.components.recorder diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 51e6f17d852..6fa04d7a578 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -515,7 +515,7 @@ fjaraskupan==2.2.0 flipr-api==1.4.2 # homeassistant.components.flux_led -flux_led==0.28.32 +flux_led==0.28.34 # homeassistant.components.homekit # homeassistant.components.recorder From d45a0cc41e790ca8ad938f8eaacf61c63a276ea1 Mon Sep 17 00:00:00 2001 From: Michael <35783820+mib1185@users.noreply.github.com> Date: Sat, 19 Nov 2022 15:02:07 +0100 Subject: [PATCH 07/13] Fix invalid configuration_url in Netatmo (#82372) --- homeassistant/components/netatmo/netatmo_entity_base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/netatmo/netatmo_entity_base.py b/homeassistant/components/netatmo/netatmo_entity_base.py index c434d370e27..78352e486e0 100644 --- a/homeassistant/components/netatmo/netatmo_entity_base.py +++ b/homeassistant/components/netatmo/netatmo_entity_base.py @@ -29,7 +29,7 @@ class NetatmoBase(Entity): self._device_name: str = "" self._id: str = "" self._model: str = "" - self._config_url: str = "" + self._config_url: str | None = None self._attr_name = None self._attr_unique_id = None self._attr_extra_state_attributes = {} From 5ec7cff3ffddb698d681379138a411ea440b54b8 Mon Sep 17 00:00:00 2001 From: TheJulianJES Date: Sun, 20 Nov 2022 15:13:19 +0100 Subject: [PATCH 08/13] Bump PyViCare to 2.19.0 (#82381) fixes undefined --- homeassistant/components/vicare/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/vicare/manifest.json b/homeassistant/components/vicare/manifest.json index c770f1b2382..0294022137c 100644 --- a/homeassistant/components/vicare/manifest.json +++ b/homeassistant/components/vicare/manifest.json @@ -3,7 +3,7 @@ "name": "Viessmann ViCare", "documentation": "https://www.home-assistant.io/integrations/vicare", "codeowners": ["@oischinger"], - "requirements": ["PyViCare==2.17.0"], + "requirements": ["PyViCare==2.19.0"], "iot_class": "cloud_polling", "config_flow": true, "dhcp": [ diff --git a/requirements_all.txt b/requirements_all.txt index 2218f2d77a4..20c5490d335 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -47,7 +47,7 @@ PyTransportNSW==0.1.1 PyTurboJPEG==1.6.7 # homeassistant.components.vicare -PyViCare==2.17.0 +PyViCare==2.19.0 # homeassistant.components.xiaomi_aqara PyXiaomiGateway==0.14.3 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 6fa04d7a578..5d7f9bb0598 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -43,7 +43,7 @@ PyTransportNSW==0.1.1 PyTurboJPEG==1.6.7 # homeassistant.components.vicare -PyViCare==2.17.0 +PyViCare==2.19.0 # homeassistant.components.xiaomi_aqara PyXiaomiGateway==0.14.3 From 018300858fc4c61f83d111c6941973fe73e93c2a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 19 Nov 2022 18:46:06 -0600 Subject: [PATCH 09/13] Bump bleak-retry-connector to 2.8.5 (#82387) changelog: https://github.com/Bluetooth-Devices/bleak-retry-connector/compare/v2.8.4...v2.8.5 from: https://github.com/esphome/esphome/pull/4049 --- homeassistant/components/bluetooth/manifest.json | 2 +- homeassistant/package_constraints.txt | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/bluetooth/manifest.json b/homeassistant/components/bluetooth/manifest.json index 2b6847b65b8..5e56d125f44 100644 --- a/homeassistant/components/bluetooth/manifest.json +++ b/homeassistant/components/bluetooth/manifest.json @@ -7,7 +7,7 @@ "quality_scale": "internal", "requirements": [ "bleak==0.19.2", - "bleak-retry-connector==2.8.4", + "bleak-retry-connector==2.8.5", "bluetooth-adapters==0.7.0", "bluetooth-auto-recovery==0.3.6", "dbus-fast==1.61.1" diff --git a/homeassistant/package_constraints.txt b/homeassistant/package_constraints.txt index 4641c32d562..b83c9c8db01 100644 --- a/homeassistant/package_constraints.txt +++ b/homeassistant/package_constraints.txt @@ -10,7 +10,7 @@ atomicwrites-homeassistant==1.4.1 attrs==21.2.0 awesomeversion==22.9.0 bcrypt==3.1.7 -bleak-retry-connector==2.8.4 +bleak-retry-connector==2.8.5 bleak==0.19.2 bluetooth-adapters==0.7.0 bluetooth-auto-recovery==0.3.6 diff --git a/requirements_all.txt b/requirements_all.txt index 20c5490d335..bc363d39203 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -413,7 +413,7 @@ bimmer_connected==0.10.4 bizkaibus==0.1.1 # homeassistant.components.bluetooth -bleak-retry-connector==2.8.4 +bleak-retry-connector==2.8.5 # homeassistant.components.bluetooth bleak==0.19.2 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 5d7f9bb0598..f7c09893df4 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -337,7 +337,7 @@ bellows==0.34.2 bimmer_connected==0.10.4 # homeassistant.components.bluetooth -bleak-retry-connector==2.8.4 +bleak-retry-connector==2.8.5 # homeassistant.components.bluetooth bleak==0.19.2 From 243941f3fd6b2964aac3023ec933bb8454e27e5c Mon Sep 17 00:00:00 2001 From: Marvin Wichmann Date: Sun, 20 Nov 2022 15:12:38 +0100 Subject: [PATCH 10/13] Update xknx to 1.2.1 (#82404) --- homeassistant/components/knx/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/knx/manifest.json b/homeassistant/components/knx/manifest.json index b29e44490e9..a7436ef1ae3 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==1.2.0"], + "requirements": ["xknx==1.2.1"], "codeowners": ["@Julius2342", "@farmio", "@marvin-w"], "quality_scale": "platinum", "iot_class": "local_push", diff --git a/requirements_all.txt b/requirements_all.txt index bc363d39203..4b9242fe2a5 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2563,7 +2563,7 @@ xboxapi==2.0.1 xiaomi-ble==0.10.0 # homeassistant.components.knx -xknx==1.2.0 +xknx==1.2.1 # homeassistant.components.bluesound # homeassistant.components.fritz diff --git a/requirements_test_all.txt b/requirements_test_all.txt index f7c09893df4..506a740b2aa 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1776,7 +1776,7 @@ xbox-webapi==2.0.11 xiaomi-ble==0.10.0 # homeassistant.components.knx -xknx==1.2.0 +xknx==1.2.1 # homeassistant.components.bluesound # homeassistant.components.fritz From b578a76cb94572862a0e2029e24e1a04e4521160 Mon Sep 17 00:00:00 2001 From: "David F. Mulcahey" Date: Sun, 20 Nov 2022 10:39:47 -0500 Subject: [PATCH 11/13] Attempt to fix occasional Flo timeouts (#82408) * Attempt to fix occasional Flo timeouts * remove gather --- homeassistant/components/flo/device.py | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/homeassistant/components/flo/device.py b/homeassistant/components/flo/device.py index ca4b6aa6234..d6e05c17136 100644 --- a/homeassistant/components/flo/device.py +++ b/homeassistant/components/flo/device.py @@ -1,7 +1,6 @@ """Flo device object.""" from __future__ import annotations -import asyncio from datetime import datetime, timedelta from typing import Any @@ -40,14 +39,10 @@ class FloDeviceDataUpdateCoordinator(DataUpdateCoordinator): async def _async_update_data(self): """Update data via library.""" try: - async with timeout(10): - await asyncio.gather( - *[ - self.send_presence_ping(), - self._update_device(), - self._update_consumption_data(), - ] - ) + async with timeout(20): + await self.send_presence_ping() + await self._update_device() + await self._update_consumption_data() except (RequestError) as error: raise UpdateFailed(error) from error From 3ab1df4660c0de42edace3139b078ee96584764c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 20 Nov 2022 09:38:30 -0600 Subject: [PATCH 12/13] Prevent powerwall from switching addresses if its online (#82410) * Prevent powerwall from switching addresses if its online If the wifi interface was discovered we would switch the ip address in the entry to the wifi ip even if it was connected via ethernet * cover * more cover --- .../components/powerwall/__init__.py | 13 +- .../components/powerwall/config_flow.py | 49 ++++++- .../components/powerwall/test_config_flow.py | 136 +++++++++++++++++- 3 files changed, 194 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/powerwall/__init__.py b/homeassistant/components/powerwall/__init__.py index 2fdf3d61d20..d8550e6f46b 100644 --- a/homeassistant/components/powerwall/__init__.py +++ b/homeassistant/components/powerwall/__init__.py @@ -18,7 +18,7 @@ from tesla_powerwall import ( from homeassistant.components import persistent_notification from homeassistant.config_entries import ConfigEntry from homeassistant.const import CONF_IP_ADDRESS, CONF_PASSWORD, Platform -from homeassistant.core import HomeAssistant +from homeassistant.core import HomeAssistant, callback from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady import homeassistant.helpers.config_validation as cv from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed @@ -221,6 +221,17 @@ def _fetch_powerwall_data(power_wall: Powerwall) -> PowerwallData: ) +@callback +def async_last_update_was_successful(hass: HomeAssistant, entry: ConfigEntry) -> bool: + """Return True if the last update was successful.""" + return bool( + (domain_data := hass.data.get(DOMAIN)) + and (entry_data := domain_data.get(entry.entry_id)) + and (coordinator := entry_data.get(POWERWALL_COORDINATOR)) + and coordinator.last_update_success + ) + + async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Unload a config entry.""" unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS) diff --git a/homeassistant/components/powerwall/config_flow.py b/homeassistant/components/powerwall/config_flow.py index b9f6f3969fd..6e4f40bf01b 100644 --- a/homeassistant/components/powerwall/config_flow.py +++ b/homeassistant/components/powerwall/config_flow.py @@ -20,11 +20,18 @@ from homeassistant.const import CONF_IP_ADDRESS, CONF_PASSWORD from homeassistant.data_entry_flow import FlowResult from homeassistant.util.network import is_ip_address +from . import async_last_update_was_successful from .const import DOMAIN _LOGGER = logging.getLogger(__name__) +ENTRY_FAILURE_STATES = { + config_entries.ConfigEntryState.SETUP_ERROR, + config_entries.ConfigEntryState.SETUP_RETRY, +} + + def _login_and_fetch_site_info( power_wall: Powerwall, password: str ) -> tuple[SiteInfo, str]: @@ -34,6 +41,17 @@ def _login_and_fetch_site_info( return power_wall.get_site_info(), power_wall.get_gateway_din() +def _powerwall_is_reachable(ip_address: str, password: str) -> bool: + """Check if the powerwall is reachable.""" + try: + Powerwall(ip_address).login(password) + except AccessDeniedError: + return True + except PowerwallUnreachableError: + return False + return True + + async def validate_input( hass: core.HomeAssistant, data: dict[str, str] ) -> dict[str, str]: @@ -69,13 +87,31 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): self.title: str | None = None self.reauth_entry: config_entries.ConfigEntry | None = None + async def _async_powerwall_is_offline( + self, entry: config_entries.ConfigEntry + ) -> bool: + """Check if the power wall is offline. + + We define offline by the config entry + is in a failure/retry state or the updates + are failing and the powerwall is unreachable + since device may be updating. + """ + ip_address = entry.data[CONF_IP_ADDRESS] + password = entry.data[CONF_PASSWORD] + return bool( + entry.state in ENTRY_FAILURE_STATES + or not async_last_update_was_successful(self.hass, entry) + ) and not await self.hass.async_add_executor_job( + _powerwall_is_reachable, ip_address, password + ) + async def async_step_dhcp(self, discovery_info: dhcp.DhcpServiceInfo) -> FlowResult: """Handle dhcp discovery.""" self.ip_address = discovery_info.ip gateway_din = discovery_info.hostname.upper() # The hostname is the gateway_din (unique_id) await self.async_set_unique_id(gateway_din) - self._abort_if_unique_id_configured(updates={CONF_IP_ADDRESS: self.ip_address}) for entry in self._async_current_entries(include_ignore=False): if entry.data[CONF_IP_ADDRESS] == discovery_info.ip: if entry.unique_id is not None and is_ip_address(entry.unique_id): @@ -86,6 +122,17 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): self.hass.config_entries.async_reload(entry.entry_id) ) return self.async_abort(reason="already_configured") + if entry.unique_id == gateway_din: + if await self._async_powerwall_is_offline(entry): + if self.hass.config_entries.async_update_entry( + entry, data={**entry.data, CONF_IP_ADDRESS: self.ip_address} + ): + self.hass.async_create_task( + self.hass.config_entries.async_reload(entry.entry_id) + ) + return self.async_abort(reason="already_configured") + # Still need to abort for ignored entries + self._abort_if_unique_id_configured() self.context["title_placeholders"] = { "name": gateway_din, "ip_address": self.ip_address, diff --git a/tests/components/powerwall/test_config_flow.py b/tests/components/powerwall/test_config_flow.py index f4dcfd87b8b..11861a8238c 100644 --- a/tests/components/powerwall/test_config_flow.py +++ b/tests/components/powerwall/test_config_flow.py @@ -1,6 +1,6 @@ """Test the Powerwall config flow.""" -from unittest.mock import patch +from unittest.mock import MagicMock, patch from tesla_powerwall import ( AccessDeniedError, @@ -18,6 +18,7 @@ from .mocks import ( MOCK_GATEWAY_DIN, _mock_powerwall_side_effect, _mock_powerwall_site_name, + _mock_powerwall_with_fixtures, ) from tests.common import MockConfigEntry @@ -351,7 +352,7 @@ async def test_dhcp_discovery_update_ip_address(hass): unique_id=MOCK_GATEWAY_DIN, ) entry.add_to_hass(hass) - mock_powerwall = await _mock_powerwall_site_name(hass, "Some site") + mock_powerwall = MagicMock(login=MagicMock(side_effect=PowerwallUnreachableError)) with patch( "homeassistant.components.powerwall.config_flow.Powerwall", @@ -375,6 +376,70 @@ async def test_dhcp_discovery_update_ip_address(hass): assert entry.data[CONF_IP_ADDRESS] == "1.1.1.1" +async def test_dhcp_discovery_does_not_update_ip_when_auth_fails(hass): + """Test we do not switch to another interface when auth is failing.""" + entry = MockConfigEntry( + domain=DOMAIN, + data=VALID_CONFIG, + unique_id=MOCK_GATEWAY_DIN, + ) + entry.add_to_hass(hass) + mock_powerwall = MagicMock(login=MagicMock(side_effect=AccessDeniedError("any"))) + + with patch( + "homeassistant.components.powerwall.config_flow.Powerwall", + return_value=mock_powerwall, + ), patch( + "homeassistant.components.powerwall.async_setup_entry", + return_value=True, + ): + result = await hass.config_entries.flow.async_init( + DOMAIN, + context={"source": config_entries.SOURCE_DHCP}, + data=dhcp.DhcpServiceInfo( + ip="1.1.1.1", + macaddress="AA:BB:CC:DD:EE:FF", + hostname=MOCK_GATEWAY_DIN.lower(), + ), + ) + await hass.async_block_till_done() + assert result["type"] == FlowResultType.ABORT + assert result["reason"] == "already_configured" + assert entry.data[CONF_IP_ADDRESS] == "1.2.3.4" + + +async def test_dhcp_discovery_does_not_update_ip_when_auth_successful(hass): + """Test we do not switch to another interface when auth is successful.""" + entry = MockConfigEntry( + domain=DOMAIN, + data=VALID_CONFIG, + unique_id=MOCK_GATEWAY_DIN, + ) + entry.add_to_hass(hass) + mock_powerwall = MagicMock(login=MagicMock(return_value=True)) + + with patch( + "homeassistant.components.powerwall.config_flow.Powerwall", + return_value=mock_powerwall, + ), patch( + "homeassistant.components.powerwall.async_setup_entry", + return_value=True, + ): + result = await hass.config_entries.flow.async_init( + DOMAIN, + context={"source": config_entries.SOURCE_DHCP}, + data=dhcp.DhcpServiceInfo( + ip="1.1.1.1", + macaddress="AA:BB:CC:DD:EE:FF", + hostname=MOCK_GATEWAY_DIN.lower(), + ), + ) + await hass.async_block_till_done() + assert result["type"] == FlowResultType.ABORT + assert result["reason"] == "already_configured" + assert entry.data[CONF_IP_ADDRESS] == "1.2.3.4" + + async def test_dhcp_discovery_updates_unique_id(hass): """Test we can update the unique id from dhcp.""" entry = MockConfigEntry( @@ -406,3 +471,70 @@ async def test_dhcp_discovery_updates_unique_id(hass): assert result["reason"] == "already_configured" assert entry.data[CONF_IP_ADDRESS] == "1.2.3.4" assert entry.unique_id == MOCK_GATEWAY_DIN + + +async def test_dhcp_discovery_updates_unique_id_when_entry_is_failed(hass): + """Test we can update the unique id from dhcp in a failed state.""" + entry = MockConfigEntry( + domain=DOMAIN, + data=VALID_CONFIG, + unique_id="1.2.3.4", + ) + entry.add_to_hass(hass) + entry.state = config_entries.ConfigEntryState.SETUP_ERROR + mock_powerwall = await _mock_powerwall_site_name(hass, "Some site") + + with patch( + "homeassistant.components.powerwall.config_flow.Powerwall", + return_value=mock_powerwall, + ), patch( + "homeassistant.components.powerwall.async_setup_entry", + return_value=True, + ): + result = await hass.config_entries.flow.async_init( + DOMAIN, + context={"source": config_entries.SOURCE_DHCP}, + data=dhcp.DhcpServiceInfo( + ip="1.2.3.4", + macaddress="AA:BB:CC:DD:EE:FF", + hostname=MOCK_GATEWAY_DIN.lower(), + ), + ) + await hass.async_block_till_done() + assert result["type"] == FlowResultType.ABORT + assert result["reason"] == "already_configured" + assert entry.data[CONF_IP_ADDRESS] == "1.2.3.4" + assert entry.unique_id == MOCK_GATEWAY_DIN + + +async def test_discovered_wifi_does_not_update_ip_if_is_still_online(hass) -> None: + """Test a discovery does not update the ip unless the powerwall at the old ip is offline.""" + entry = MockConfigEntry( + domain=DOMAIN, + data=VALID_CONFIG, + unique_id=MOCK_GATEWAY_DIN, + ) + entry.add_to_hass(hass) + mock_powerwall = await _mock_powerwall_with_fixtures(hass) + + with patch( + "homeassistant.components.powerwall.config_flow.Powerwall", + return_value=mock_powerwall, + ), patch( + "homeassistant.components.powerwall.Powerwall", return_value=mock_powerwall + ): + assert await hass.config_entries.async_setup(entry.entry_id) + await hass.async_block_till_done() + result = await hass.config_entries.flow.async_init( + DOMAIN, + context={"source": config_entries.SOURCE_DHCP}, + data=dhcp.DhcpServiceInfo( + ip="1.2.3.5", + macaddress="AA:BB:CC:DD:EE:FF", + hostname=MOCK_GATEWAY_DIN.lower(), + ), + ) + await hass.async_block_till_done() + assert result["type"] == FlowResultType.ABORT + assert result["reason"] == "already_configured" + assert entry.data[CONF_IP_ADDRESS] == "1.2.3.4" From 2a384987e7b5d7f94f520972e8da287a8f8bc49a Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sun, 20 Nov 2022 15:27:43 -0500 Subject: [PATCH 13/13] Bumped version to 2022.11.4 --- 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 7b4230c79f1..0fe06355342 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -8,7 +8,7 @@ from .backports.enum import StrEnum APPLICATION_NAME: Final = "HomeAssistant" MAJOR_VERSION: Final = 2022 MINOR_VERSION: Final = 11 -PATCH_VERSION: Final = "3" +PATCH_VERSION: Final = "4" __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 d60943ab098..0562e18b5a5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "homeassistant" -version = "2022.11.3" +version = "2022.11.4" license = {text = "Apache-2.0"} description = "Open-source home automation platform running on Python 3." readme = "README.rst"