mirror of
https://github.com/home-assistant/core.git
synced 2025-07-21 20:27:08 +00:00
2022.11.4 (#82428)
This commit is contained in:
commit
5fe426a4fc
@ -7,7 +7,7 @@
|
|||||||
"quality_scale": "internal",
|
"quality_scale": "internal",
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"bleak==0.19.2",
|
"bleak==0.19.2",
|
||||||
"bleak-retry-connector==2.8.4",
|
"bleak-retry-connector==2.8.5",
|
||||||
"bluetooth-adapters==0.7.0",
|
"bluetooth-adapters==0.7.0",
|
||||||
"bluetooth-auto-recovery==0.3.6",
|
"bluetooth-auto-recovery==0.3.6",
|
||||||
"dbus-fast==1.61.1"
|
"dbus-fast==1.61.1"
|
||||||
|
@ -612,7 +612,7 @@ class TimeSMAFilter(Filter, SensorEntity):
|
|||||||
|
|
||||||
moving_sum = 0
|
moving_sum = 0
|
||||||
start = new_state.timestamp - self._time_window
|
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:
|
for state in self.queue:
|
||||||
moving_sum += (state.timestamp - start).total_seconds() * prev_state.state
|
moving_sum += (state.timestamp - start).total_seconds() * prev_state.state
|
||||||
start = state.timestamp
|
start = state.timestamp
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
"""Flo device object."""
|
"""Flo device object."""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import asyncio
|
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
@ -40,14 +39,10 @@ class FloDeviceDataUpdateCoordinator(DataUpdateCoordinator):
|
|||||||
async def _async_update_data(self):
|
async def _async_update_data(self):
|
||||||
"""Update data via library."""
|
"""Update data via library."""
|
||||||
try:
|
try:
|
||||||
async with timeout(10):
|
async with timeout(20):
|
||||||
await asyncio.gather(
|
await self.send_presence_ping()
|
||||||
*[
|
await self._update_device()
|
||||||
self.send_presence_ping(),
|
await self._update_consumption_data()
|
||||||
self._update_device(),
|
|
||||||
self._update_consumption_data(),
|
|
||||||
]
|
|
||||||
)
|
|
||||||
except (RequestError) as error:
|
except (RequestError) as error:
|
||||||
raise UpdateFailed(error) from error
|
raise UpdateFailed(error) from error
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
"config_flow": true,
|
"config_flow": true,
|
||||||
"dependencies": ["network"],
|
"dependencies": ["network"],
|
||||||
"documentation": "https://www.home-assistant.io/integrations/flux_led",
|
"documentation": "https://www.home-assistant.io/integrations/flux_led",
|
||||||
"requirements": ["flux_led==0.28.32"],
|
"requirements": ["flux_led==0.28.34"],
|
||||||
"quality_scale": "platinum",
|
"quality_scale": "platinum",
|
||||||
"codeowners": ["@icemanch", "@bdraco"],
|
"codeowners": ["@icemanch", "@bdraco"],
|
||||||
"iot_class": "local_push",
|
"iot_class": "local_push",
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"name": "KNX",
|
"name": "KNX",
|
||||||
"config_flow": true,
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/integrations/knx",
|
"documentation": "https://www.home-assistant.io/integrations/knx",
|
||||||
"requirements": ["xknx==1.2.0"],
|
"requirements": ["xknx==1.2.1"],
|
||||||
"codeowners": ["@Julius2342", "@farmio", "@marvin-w"],
|
"codeowners": ["@Julius2342", "@farmio", "@marvin-w"],
|
||||||
"quality_scale": "platinum",
|
"quality_scale": "platinum",
|
||||||
"iot_class": "local_push",
|
"iot_class": "local_push",
|
||||||
|
@ -375,4 +375,3 @@ async def async_reset_platform(hass: HomeAssistant, integration_name: str) -> No
|
|||||||
hubs = hass.data[DOMAIN]
|
hubs = hass.data[DOMAIN]
|
||||||
for name in hubs:
|
for name in hubs:
|
||||||
await hubs[name].async_close()
|
await hubs[name].async_close()
|
||||||
del hass.data[DOMAIN]
|
|
||||||
|
@ -132,6 +132,12 @@ async def async_modbus_setup(
|
|||||||
|
|
||||||
await async_setup_reload_service(hass, DOMAIN, [DOMAIN])
|
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 = {}
|
hass.data[DOMAIN] = hub_collect = {}
|
||||||
for conf_hub in config[DOMAIN]:
|
for conf_hub in config[DOMAIN]:
|
||||||
my_hub = ModbusHub(hass, conf_hub)
|
my_hub = ModbusHub(hass, conf_hub)
|
||||||
|
@ -29,7 +29,7 @@ class NetatmoBase(Entity):
|
|||||||
self._device_name: str = ""
|
self._device_name: str = ""
|
||||||
self._id: str = ""
|
self._id: str = ""
|
||||||
self._model: str = ""
|
self._model: str = ""
|
||||||
self._config_url: str = ""
|
self._config_url: str | None = None
|
||||||
self._attr_name = None
|
self._attr_name = None
|
||||||
self._attr_unique_id = None
|
self._attr_unique_id = None
|
||||||
self._attr_extra_state_attributes = {}
|
self._attr_extra_state_attributes = {}
|
||||||
|
@ -19,6 +19,7 @@ from homeassistant.const import (
|
|||||||
ENERGY_KILO_WATT_HOUR,
|
ENERGY_KILO_WATT_HOUR,
|
||||||
ENERGY_MEGA_WATT_HOUR,
|
ENERGY_MEGA_WATT_HOUR,
|
||||||
ENERGY_WATT_HOUR,
|
ENERGY_WATT_HOUR,
|
||||||
|
POWER_KILO_WATT,
|
||||||
POWER_WATT,
|
POWER_WATT,
|
||||||
TEMP_CELSIUS,
|
TEMP_CELSIUS,
|
||||||
TEMP_FAHRENHEIT,
|
TEMP_FAHRENHEIT,
|
||||||
@ -80,6 +81,13 @@ UNIT_DESCRIPTIONS = {
|
|||||||
state_class=SensorStateClass.MEASUREMENT,
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
native_unit_of_measurement=POWER_WATT,
|
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(
|
"Wh": SensorEntityDescription(
|
||||||
key="Wh",
|
key="Wh",
|
||||||
entity_category=EntityCategory.DIAGNOSTIC,
|
entity_category=EntityCategory.DIAGNOSTIC,
|
||||||
|
@ -18,7 +18,7 @@ from tesla_powerwall import (
|
|||||||
from homeassistant.components import persistent_notification
|
from homeassistant.components import persistent_notification
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import CONF_IP_ADDRESS, CONF_PASSWORD, Platform
|
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
|
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
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:
|
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||||
"""Unload a config entry."""
|
"""Unload a config entry."""
|
||||||
unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
|
unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
|
||||||
|
@ -20,11 +20,18 @@ from homeassistant.const import CONF_IP_ADDRESS, CONF_PASSWORD
|
|||||||
from homeassistant.data_entry_flow import FlowResult
|
from homeassistant.data_entry_flow import FlowResult
|
||||||
from homeassistant.util.network import is_ip_address
|
from homeassistant.util.network import is_ip_address
|
||||||
|
|
||||||
|
from . import async_last_update_was_successful
|
||||||
from .const import DOMAIN
|
from .const import DOMAIN
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
ENTRY_FAILURE_STATES = {
|
||||||
|
config_entries.ConfigEntryState.SETUP_ERROR,
|
||||||
|
config_entries.ConfigEntryState.SETUP_RETRY,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def _login_and_fetch_site_info(
|
def _login_and_fetch_site_info(
|
||||||
power_wall: Powerwall, password: str
|
power_wall: Powerwall, password: str
|
||||||
) -> tuple[SiteInfo, 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()
|
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(
|
async def validate_input(
|
||||||
hass: core.HomeAssistant, data: dict[str, str]
|
hass: core.HomeAssistant, data: dict[str, str]
|
||||||
) -> dict[str, str]:
|
) -> dict[str, str]:
|
||||||
@ -69,13 +87,31 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
self.title: str | None = None
|
self.title: str | None = None
|
||||||
self.reauth_entry: config_entries.ConfigEntry | 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:
|
async def async_step_dhcp(self, discovery_info: dhcp.DhcpServiceInfo) -> FlowResult:
|
||||||
"""Handle dhcp discovery."""
|
"""Handle dhcp discovery."""
|
||||||
self.ip_address = discovery_info.ip
|
self.ip_address = discovery_info.ip
|
||||||
gateway_din = discovery_info.hostname.upper()
|
gateway_din = discovery_info.hostname.upper()
|
||||||
# The hostname is the gateway_din (unique_id)
|
# The hostname is the gateway_din (unique_id)
|
||||||
await self.async_set_unique_id(gateway_din)
|
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):
|
for entry in self._async_current_entries(include_ignore=False):
|
||||||
if entry.data[CONF_IP_ADDRESS] == discovery_info.ip:
|
if entry.data[CONF_IP_ADDRESS] == discovery_info.ip:
|
||||||
if entry.unique_id is not None and is_ip_address(entry.unique_id):
|
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)
|
self.hass.config_entries.async_reload(entry.entry_id)
|
||||||
)
|
)
|
||||||
return self.async_abort(reason="already_configured")
|
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"] = {
|
self.context["title_placeholders"] = {
|
||||||
"name": gateway_din,
|
"name": gateway_din,
|
||||||
"ip_address": self.ip_address,
|
"ip_address": self.ip_address,
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"name": "RainMachine",
|
"name": "RainMachine",
|
||||||
"config_flow": true,
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/integrations/rainmachine",
|
"documentation": "https://www.home-assistant.io/integrations/rainmachine",
|
||||||
"requirements": ["regenmaschine==2022.10.0"],
|
"requirements": ["regenmaschine==2022.11.0"],
|
||||||
"codeowners": ["@bachya"],
|
"codeowners": ["@bachya"],
|
||||||
"iot_class": "local_polling",
|
"iot_class": "local_polling",
|
||||||
"homekit": {
|
"homekit": {
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"name": "SMA Solar",
|
"name": "SMA Solar",
|
||||||
"config_flow": true,
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/integrations/sma",
|
"documentation": "https://www.home-assistant.io/integrations/sma",
|
||||||
"requirements": ["pysma==0.7.2"],
|
"requirements": ["pysma==0.7.3"],
|
||||||
"codeowners": ["@kellerza", "@rklomp"],
|
"codeowners": ["@kellerza", "@rklomp"],
|
||||||
"iot_class": "local_polling",
|
"iot_class": "local_polling",
|
||||||
"loggers": ["pysma"]
|
"loggers": ["pysma"]
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"name": "Viessmann ViCare",
|
"name": "Viessmann ViCare",
|
||||||
"documentation": "https://www.home-assistant.io/integrations/vicare",
|
"documentation": "https://www.home-assistant.io/integrations/vicare",
|
||||||
"codeowners": ["@oischinger"],
|
"codeowners": ["@oischinger"],
|
||||||
"requirements": ["PyViCare==2.17.0"],
|
"requirements": ["PyViCare==2.19.0"],
|
||||||
"iot_class": "cloud_polling",
|
"iot_class": "cloud_polling",
|
||||||
"config_flow": true,
|
"config_flow": true,
|
||||||
"dhcp": [
|
"dhcp": [
|
||||||
|
@ -8,7 +8,7 @@ from .backports.enum import StrEnum
|
|||||||
APPLICATION_NAME: Final = "HomeAssistant"
|
APPLICATION_NAME: Final = "HomeAssistant"
|
||||||
MAJOR_VERSION: Final = 2022
|
MAJOR_VERSION: Final = 2022
|
||||||
MINOR_VERSION: Final = 11
|
MINOR_VERSION: Final = 11
|
||||||
PATCH_VERSION: Final = "3"
|
PATCH_VERSION: Final = "4"
|
||||||
__short_version__: Final = f"{MAJOR_VERSION}.{MINOR_VERSION}"
|
__short_version__: Final = f"{MAJOR_VERSION}.{MINOR_VERSION}"
|
||||||
__version__: Final = f"{__short_version__}.{PATCH_VERSION}"
|
__version__: Final = f"{__short_version__}.{PATCH_VERSION}"
|
||||||
REQUIRED_PYTHON_VER: Final[tuple[int, int, int]] = (3, 9, 0)
|
REQUIRED_PYTHON_VER: Final[tuple[int, int, int]] = (3, 9, 0)
|
||||||
|
@ -10,7 +10,7 @@ atomicwrites-homeassistant==1.4.1
|
|||||||
attrs==21.2.0
|
attrs==21.2.0
|
||||||
awesomeversion==22.9.0
|
awesomeversion==22.9.0
|
||||||
bcrypt==3.1.7
|
bcrypt==3.1.7
|
||||||
bleak-retry-connector==2.8.4
|
bleak-retry-connector==2.8.5
|
||||||
bleak==0.19.2
|
bleak==0.19.2
|
||||||
bluetooth-adapters==0.7.0
|
bluetooth-adapters==0.7.0
|
||||||
bluetooth-auto-recovery==0.3.6
|
bluetooth-auto-recovery==0.3.6
|
||||||
|
@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "homeassistant"
|
name = "homeassistant"
|
||||||
version = "2022.11.3"
|
version = "2022.11.4"
|
||||||
license = {text = "Apache-2.0"}
|
license = {text = "Apache-2.0"}
|
||||||
description = "Open-source home automation platform running on Python 3."
|
description = "Open-source home automation platform running on Python 3."
|
||||||
readme = "README.rst"
|
readme = "README.rst"
|
||||||
|
@ -47,7 +47,7 @@ PyTransportNSW==0.1.1
|
|||||||
PyTurboJPEG==1.6.7
|
PyTurboJPEG==1.6.7
|
||||||
|
|
||||||
# homeassistant.components.vicare
|
# homeassistant.components.vicare
|
||||||
PyViCare==2.17.0
|
PyViCare==2.19.0
|
||||||
|
|
||||||
# homeassistant.components.xiaomi_aqara
|
# homeassistant.components.xiaomi_aqara
|
||||||
PyXiaomiGateway==0.14.3
|
PyXiaomiGateway==0.14.3
|
||||||
@ -413,7 +413,7 @@ bimmer_connected==0.10.4
|
|||||||
bizkaibus==0.1.1
|
bizkaibus==0.1.1
|
||||||
|
|
||||||
# homeassistant.components.bluetooth
|
# homeassistant.components.bluetooth
|
||||||
bleak-retry-connector==2.8.4
|
bleak-retry-connector==2.8.5
|
||||||
|
|
||||||
# homeassistant.components.bluetooth
|
# homeassistant.components.bluetooth
|
||||||
bleak==0.19.2
|
bleak==0.19.2
|
||||||
@ -693,7 +693,7 @@ fjaraskupan==2.2.0
|
|||||||
flipr-api==1.4.2
|
flipr-api==1.4.2
|
||||||
|
|
||||||
# homeassistant.components.flux_led
|
# homeassistant.components.flux_led
|
||||||
flux_led==0.28.32
|
flux_led==0.28.34
|
||||||
|
|
||||||
# homeassistant.components.homekit
|
# homeassistant.components.homekit
|
||||||
# homeassistant.components.recorder
|
# homeassistant.components.recorder
|
||||||
@ -1893,7 +1893,7 @@ pysignalclirestapi==0.3.18
|
|||||||
pyskyqhub==0.1.4
|
pyskyqhub==0.1.4
|
||||||
|
|
||||||
# homeassistant.components.sma
|
# homeassistant.components.sma
|
||||||
pysma==0.7.2
|
pysma==0.7.3
|
||||||
|
|
||||||
# homeassistant.components.smappee
|
# homeassistant.components.smappee
|
||||||
pysmappee==0.2.29
|
pysmappee==0.2.29
|
||||||
@ -2153,7 +2153,7 @@ raincloudy==0.0.7
|
|||||||
raspyrfm-client==1.2.8
|
raspyrfm-client==1.2.8
|
||||||
|
|
||||||
# homeassistant.components.rainmachine
|
# homeassistant.components.rainmachine
|
||||||
regenmaschine==2022.10.0
|
regenmaschine==2022.11.0
|
||||||
|
|
||||||
# homeassistant.components.renault
|
# homeassistant.components.renault
|
||||||
renault-api==0.1.11
|
renault-api==0.1.11
|
||||||
@ -2563,7 +2563,7 @@ xboxapi==2.0.1
|
|||||||
xiaomi-ble==0.10.0
|
xiaomi-ble==0.10.0
|
||||||
|
|
||||||
# homeassistant.components.knx
|
# homeassistant.components.knx
|
||||||
xknx==1.2.0
|
xknx==1.2.1
|
||||||
|
|
||||||
# homeassistant.components.bluesound
|
# homeassistant.components.bluesound
|
||||||
# homeassistant.components.fritz
|
# homeassistant.components.fritz
|
||||||
|
@ -43,7 +43,7 @@ PyTransportNSW==0.1.1
|
|||||||
PyTurboJPEG==1.6.7
|
PyTurboJPEG==1.6.7
|
||||||
|
|
||||||
# homeassistant.components.vicare
|
# homeassistant.components.vicare
|
||||||
PyViCare==2.17.0
|
PyViCare==2.19.0
|
||||||
|
|
||||||
# homeassistant.components.xiaomi_aqara
|
# homeassistant.components.xiaomi_aqara
|
||||||
PyXiaomiGateway==0.14.3
|
PyXiaomiGateway==0.14.3
|
||||||
@ -337,7 +337,7 @@ bellows==0.34.2
|
|||||||
bimmer_connected==0.10.4
|
bimmer_connected==0.10.4
|
||||||
|
|
||||||
# homeassistant.components.bluetooth
|
# homeassistant.components.bluetooth
|
||||||
bleak-retry-connector==2.8.4
|
bleak-retry-connector==2.8.5
|
||||||
|
|
||||||
# homeassistant.components.bluetooth
|
# homeassistant.components.bluetooth
|
||||||
bleak==0.19.2
|
bleak==0.19.2
|
||||||
@ -515,7 +515,7 @@ fjaraskupan==2.2.0
|
|||||||
flipr-api==1.4.2
|
flipr-api==1.4.2
|
||||||
|
|
||||||
# homeassistant.components.flux_led
|
# homeassistant.components.flux_led
|
||||||
flux_led==0.28.32
|
flux_led==0.28.34
|
||||||
|
|
||||||
# homeassistant.components.homekit
|
# homeassistant.components.homekit
|
||||||
# homeassistant.components.recorder
|
# homeassistant.components.recorder
|
||||||
@ -1334,7 +1334,7 @@ pysiaalarm==3.0.2
|
|||||||
pysignalclirestapi==0.3.18
|
pysignalclirestapi==0.3.18
|
||||||
|
|
||||||
# homeassistant.components.sma
|
# homeassistant.components.sma
|
||||||
pysma==0.7.2
|
pysma==0.7.3
|
||||||
|
|
||||||
# homeassistant.components.smappee
|
# homeassistant.components.smappee
|
||||||
pysmappee==0.2.29
|
pysmappee==0.2.29
|
||||||
@ -1489,7 +1489,7 @@ radios==0.1.1
|
|||||||
radiotherm==2.1.0
|
radiotherm==2.1.0
|
||||||
|
|
||||||
# homeassistant.components.rainmachine
|
# homeassistant.components.rainmachine
|
||||||
regenmaschine==2022.10.0
|
regenmaschine==2022.11.0
|
||||||
|
|
||||||
# homeassistant.components.renault
|
# homeassistant.components.renault
|
||||||
renault-api==0.1.11
|
renault-api==0.1.11
|
||||||
@ -1776,7 +1776,7 @@ xbox-webapi==2.0.11
|
|||||||
xiaomi-ble==0.10.0
|
xiaomi-ble==0.10.0
|
||||||
|
|
||||||
# homeassistant.components.knx
|
# homeassistant.components.knx
|
||||||
xknx==1.2.0
|
xknx==1.2.1
|
||||||
|
|
||||||
# homeassistant.components.bluesound
|
# homeassistant.components.bluesound
|
||||||
# homeassistant.components.fritz
|
# homeassistant.components.fritz
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
"""Test the Powerwall config flow."""
|
"""Test the Powerwall config flow."""
|
||||||
|
|
||||||
from unittest.mock import patch
|
from unittest.mock import MagicMock, patch
|
||||||
|
|
||||||
from tesla_powerwall import (
|
from tesla_powerwall import (
|
||||||
AccessDeniedError,
|
AccessDeniedError,
|
||||||
@ -18,6 +18,7 @@ from .mocks import (
|
|||||||
MOCK_GATEWAY_DIN,
|
MOCK_GATEWAY_DIN,
|
||||||
_mock_powerwall_side_effect,
|
_mock_powerwall_side_effect,
|
||||||
_mock_powerwall_site_name,
|
_mock_powerwall_site_name,
|
||||||
|
_mock_powerwall_with_fixtures,
|
||||||
)
|
)
|
||||||
|
|
||||||
from tests.common import MockConfigEntry
|
from tests.common import MockConfigEntry
|
||||||
@ -351,7 +352,7 @@ async def test_dhcp_discovery_update_ip_address(hass):
|
|||||||
unique_id=MOCK_GATEWAY_DIN,
|
unique_id=MOCK_GATEWAY_DIN,
|
||||||
)
|
)
|
||||||
entry.add_to_hass(hass)
|
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(
|
with patch(
|
||||||
"homeassistant.components.powerwall.config_flow.Powerwall",
|
"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"
|
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):
|
async def test_dhcp_discovery_updates_unique_id(hass):
|
||||||
"""Test we can update the unique id from dhcp."""
|
"""Test we can update the unique id from dhcp."""
|
||||||
entry = MockConfigEntry(
|
entry = MockConfigEntry(
|
||||||
@ -406,3 +471,70 @@ async def test_dhcp_discovery_updates_unique_id(hass):
|
|||||||
assert result["reason"] == "already_configured"
|
assert result["reason"] == "already_configured"
|
||||||
assert entry.data[CONF_IP_ADDRESS] == "1.2.3.4"
|
assert entry.data[CONF_IP_ADDRESS] == "1.2.3.4"
|
||||||
assert entry.unique_id == MOCK_GATEWAY_DIN
|
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"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user