Merge pull request #57944 from home-assistant/rc
This commit is contained in:
commit
388339fee2
15 changed files with 122 additions and 63 deletions
|
@ -122,7 +122,7 @@ class BMWConnectedDriveSensor(BMWConnectedDriveBaseEntity, BinarySensorEntity):
|
||||||
if has_check_control_messages:
|
if has_check_control_messages:
|
||||||
cbs_list = []
|
cbs_list = []
|
||||||
for message in check_control_messages:
|
for message in check_control_messages:
|
||||||
cbs_list.append(message.description_short)
|
cbs_list.append(message["ccmDescriptionShort"])
|
||||||
result["check_control_messages"] = cbs_list
|
result["check_control_messages"] = cbs_list
|
||||||
else:
|
else:
|
||||||
result["check_control_messages"] = "OK"
|
result["check_control_messages"] = "OK"
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
"name": "Bond",
|
"name": "Bond",
|
||||||
"config_flow": true,
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/integrations/bond",
|
"documentation": "https://www.home-assistant.io/integrations/bond",
|
||||||
"requirements": ["bond-api==0.1.13"],
|
"requirements": ["bond-api==0.1.14"],
|
||||||
"zeroconf": ["_bond._tcp.local."],
|
"zeroconf": ["_bond._tcp.local."],
|
||||||
"codeowners": ["@prystupa", "@joshs85"],
|
"codeowners": ["@prystupa", "@joshs85"],
|
||||||
"quality_scale": "platinum",
|
"quality_scale": "platinum",
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
"""The Logitech Harmony Hub integration."""
|
"""The Logitech Harmony Hub integration."""
|
||||||
import asyncio
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from homeassistant.components.remote import ATTR_ACTIVITY, ATTR_DELAY_SECS
|
from homeassistant.components.remote import ATTR_ACTIVITY, ATTR_DELAY_SECS
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import CONF_HOST, CONF_NAME, EVENT_HOMEASSISTANT_STOP
|
from homeassistant.const import CONF_HOST, CONF_NAME, EVENT_HOMEASSISTANT_STOP
|
||||||
from homeassistant.core import HomeAssistant, callback
|
from homeassistant.core import HomeAssistant, callback
|
||||||
from homeassistant.exceptions import ConfigEntryNotReady
|
|
||||||
from homeassistant.helpers import entity_registry
|
from homeassistant.helpers import entity_registry
|
||||||
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
||||||
|
|
||||||
|
@ -34,13 +32,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||||
address = entry.data[CONF_HOST]
|
address = entry.data[CONF_HOST]
|
||||||
name = entry.data[CONF_NAME]
|
name = entry.data[CONF_NAME]
|
||||||
data = HarmonyData(hass, address, name, entry.unique_id)
|
data = HarmonyData(hass, address, name, entry.unique_id)
|
||||||
try:
|
await data.connect()
|
||||||
connected_ok = await data.connect()
|
|
||||||
except (asyncio.TimeoutError, ValueError, AttributeError) as err:
|
|
||||||
raise ConfigEntryNotReady from err
|
|
||||||
|
|
||||||
if not connected_ok:
|
|
||||||
raise ConfigEntryNotReady
|
|
||||||
|
|
||||||
await _migrate_old_unique_ids(hass, entry.entry_id, data)
|
await _migrate_old_unique_ids(hass, entry.entry_id, data)
|
||||||
|
|
||||||
|
@ -51,8 +43,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||||
|
|
||||||
cancel_stop = hass.bus.async_listen(EVENT_HOMEASSISTANT_STOP, _async_on_stop)
|
cancel_stop = hass.bus.async_listen(EVENT_HOMEASSISTANT_STOP, _async_on_stop)
|
||||||
|
|
||||||
hass.data.setdefault(DOMAIN, {})
|
hass.data.setdefault(DOMAIN, {})[entry.entry_id] = {
|
||||||
hass.data[DOMAIN][entry.entry_id] = {
|
|
||||||
HARMONY_DATA: data,
|
HARMONY_DATA: data,
|
||||||
CANCEL_LISTENER: cancel_listener,
|
CANCEL_LISTENER: cancel_listener,
|
||||||
CANCEL_STOP: cancel_stop,
|
CANCEL_STOP: cancel_stop,
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
"""Config flow for Logitech Harmony Hub integration."""
|
"""Config flow for Logitech Harmony Hub integration."""
|
||||||
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
|
from aioharmony.hubconnector_websocket import HubConnector
|
||||||
|
import aiohttp
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant import config_entries, exceptions
|
from homeassistant import config_entries, exceptions
|
||||||
|
@ -94,16 +97,20 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
||||||
CONF_NAME: friendly_name,
|
CONF_NAME: friendly_name,
|
||||||
}
|
}
|
||||||
|
|
||||||
harmony = await get_harmony_client_if_available(parsed_url.hostname)
|
connector = HubConnector(parsed_url.hostname, asyncio.Queue())
|
||||||
|
try:
|
||||||
if harmony:
|
remote_id = await connector.get_remote_id()
|
||||||
unique_id = find_unique_id_for_remote(harmony)
|
except aiohttp.ClientError:
|
||||||
await self.async_set_unique_id(unique_id)
|
return self.async_abort(reason="cannot_connect")
|
||||||
self._abort_if_unique_id_configured(
|
finally:
|
||||||
updates={CONF_HOST: self.harmony_config[CONF_HOST]}
|
await connector.async_close_session()
|
||||||
)
|
|
||||||
self.harmony_config[UNIQUE_ID] = unique_id
|
|
||||||
|
|
||||||
|
unique_id = str(remote_id)
|
||||||
|
await self.async_set_unique_id(str(unique_id))
|
||||||
|
self._abort_if_unique_id_configured(
|
||||||
|
updates={CONF_HOST: self.harmony_config[CONF_HOST]}
|
||||||
|
)
|
||||||
|
self.harmony_config[UNIQUE_ID] = unique_id
|
||||||
return await self.async_step_link()
|
return await self.async_step_link()
|
||||||
|
|
||||||
async def async_step_link(self, user_input=None):
|
async def async_step_link(self, user_input=None):
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
"""Harmony data object which contains the Harmony Client."""
|
"""Harmony data object which contains the Harmony Client."""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import asyncio
|
||||||
from collections.abc import Iterable
|
from collections.abc import Iterable
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
@ -8,6 +9,8 @@ from aioharmony.const import ClientCallbackType, SendCommandDevice
|
||||||
import aioharmony.exceptions as aioexc
|
import aioharmony.exceptions as aioexc
|
||||||
from aioharmony.harmonyapi import HarmonyAPI as HarmonyClient
|
from aioharmony.harmonyapi import HarmonyAPI as HarmonyClient
|
||||||
|
|
||||||
|
from homeassistant.exceptions import ConfigEntryNotReady
|
||||||
|
|
||||||
from .const import ACTIVITY_POWER_OFF
|
from .const import ACTIVITY_POWER_OFF
|
||||||
from .subscriber import HarmonySubscriberMixin
|
from .subscriber import HarmonySubscriberMixin
|
||||||
|
|
||||||
|
@ -109,16 +112,24 @@ class HarmonyData(HarmonySubscriberMixin):
|
||||||
ip_address=self._address, callbacks=ClientCallbackType(**callbacks)
|
ip_address=self._address, callbacks=ClientCallbackType(**callbacks)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
connected = False
|
||||||
try:
|
try:
|
||||||
if not await self._client.connect():
|
connected = await self._client.connect()
|
||||||
_LOGGER.warning("%s: Unable to connect to HUB", self._name)
|
except (asyncio.TimeoutError, aioexc.TimeOut) as err:
|
||||||
await self._client.close()
|
await self._client.close()
|
||||||
return False
|
raise ConfigEntryNotReady(
|
||||||
except aioexc.TimeOut:
|
f"{self._name}: Connection timed-out to {self._address}:8088"
|
||||||
_LOGGER.warning("%s: Connection timed-out", self._name)
|
) from err
|
||||||
return False
|
except (ValueError, AttributeError) as err:
|
||||||
|
await self._client.close()
|
||||||
return True
|
raise ConfigEntryNotReady(
|
||||||
|
f"{self._name}: Error {err} while connected HUB at: {self._address}:8088"
|
||||||
|
) from err
|
||||||
|
if not connected:
|
||||||
|
await self._client.close()
|
||||||
|
raise ConfigEntryNotReady(
|
||||||
|
f"{self._name}: Unable to connect to HUB at: {self._address}:8088"
|
||||||
|
)
|
||||||
|
|
||||||
async def shutdown(self):
|
async def shutdown(self):
|
||||||
"""Close connection on shutdown."""
|
"""Close connection on shutdown."""
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
"domain": "harmony",
|
"domain": "harmony",
|
||||||
"name": "Logitech Harmony Hub",
|
"name": "Logitech Harmony Hub",
|
||||||
"documentation": "https://www.home-assistant.io/integrations/harmony",
|
"documentation": "https://www.home-assistant.io/integrations/harmony",
|
||||||
"requirements": ["aioharmony==0.2.7"],
|
"requirements": ["aioharmony==0.2.8"],
|
||||||
"codeowners": [
|
"codeowners": [
|
||||||
"@ehendrix23",
|
"@ehendrix23",
|
||||||
"@bramkragten",
|
"@bramkragten",
|
||||||
|
|
|
@ -5,6 +5,7 @@ import logging
|
||||||
from homeassistant.components.sensor import SensorEntity
|
from homeassistant.components.sensor import SensorEntity
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
DEVICE_CLASS_BATTERY,
|
DEVICE_CLASS_BATTERY,
|
||||||
|
DEVICE_CLASS_ENERGY,
|
||||||
DEVICE_CLASS_ILLUMINANCE,
|
DEVICE_CLASS_ILLUMINANCE,
|
||||||
DEVICE_CLASS_POWER,
|
DEVICE_CLASS_POWER,
|
||||||
DEVICE_CLASS_PRESSURE,
|
DEVICE_CLASS_PRESSURE,
|
||||||
|
@ -68,32 +69,32 @@ ENERGY_SENSOR_MAP = {
|
||||||
"electricity_consumed_interval": [
|
"electricity_consumed_interval": [
|
||||||
"Consumed Power Interval",
|
"Consumed Power Interval",
|
||||||
ENERGY_WATT_HOUR,
|
ENERGY_WATT_HOUR,
|
||||||
DEVICE_CLASS_POWER,
|
DEVICE_CLASS_ENERGY,
|
||||||
],
|
],
|
||||||
"electricity_consumed_peak_interval": [
|
"electricity_consumed_peak_interval": [
|
||||||
"Consumed Power Interval",
|
"Consumed Power Interval",
|
||||||
ENERGY_WATT_HOUR,
|
ENERGY_WATT_HOUR,
|
||||||
DEVICE_CLASS_POWER,
|
DEVICE_CLASS_ENERGY,
|
||||||
],
|
],
|
||||||
"electricity_consumed_off_peak_interval": [
|
"electricity_consumed_off_peak_interval": [
|
||||||
"Consumed Power Interval (off peak)",
|
"Consumed Power Interval (off peak)",
|
||||||
ENERGY_WATT_HOUR,
|
ENERGY_WATT_HOUR,
|
||||||
DEVICE_CLASS_POWER,
|
DEVICE_CLASS_ENERGY,
|
||||||
],
|
],
|
||||||
"electricity_produced_interval": [
|
"electricity_produced_interval": [
|
||||||
"Produced Power Interval",
|
"Produced Power Interval",
|
||||||
ENERGY_WATT_HOUR,
|
ENERGY_WATT_HOUR,
|
||||||
DEVICE_CLASS_POWER,
|
DEVICE_CLASS_ENERGY,
|
||||||
],
|
],
|
||||||
"electricity_produced_peak_interval": [
|
"electricity_produced_peak_interval": [
|
||||||
"Produced Power Interval",
|
"Produced Power Interval",
|
||||||
ENERGY_WATT_HOUR,
|
ENERGY_WATT_HOUR,
|
||||||
DEVICE_CLASS_POWER,
|
DEVICE_CLASS_ENERGY,
|
||||||
],
|
],
|
||||||
"electricity_produced_off_peak_interval": [
|
"electricity_produced_off_peak_interval": [
|
||||||
"Produced Power Interval (off peak)",
|
"Produced Power Interval (off peak)",
|
||||||
ENERGY_WATT_HOUR,
|
ENERGY_WATT_HOUR,
|
||||||
DEVICE_CLASS_POWER,
|
DEVICE_CLASS_ENERGY,
|
||||||
],
|
],
|
||||||
"electricity_consumed_off_peak_point": [
|
"electricity_consumed_off_peak_point": [
|
||||||
"Current Consumed Power (off peak)",
|
"Current Consumed Power (off peak)",
|
||||||
|
@ -108,12 +109,12 @@ ENERGY_SENSOR_MAP = {
|
||||||
"electricity_consumed_off_peak_cumulative": [
|
"electricity_consumed_off_peak_cumulative": [
|
||||||
"Cumulative Consumed Power (off peak)",
|
"Cumulative Consumed Power (off peak)",
|
||||||
ENERGY_KILO_WATT_HOUR,
|
ENERGY_KILO_WATT_HOUR,
|
||||||
DEVICE_CLASS_POWER,
|
DEVICE_CLASS_ENERGY,
|
||||||
],
|
],
|
||||||
"electricity_consumed_peak_cumulative": [
|
"electricity_consumed_peak_cumulative": [
|
||||||
"Cumulative Consumed Power",
|
"Cumulative Consumed Power",
|
||||||
ENERGY_KILO_WATT_HOUR,
|
ENERGY_KILO_WATT_HOUR,
|
||||||
DEVICE_CLASS_POWER,
|
DEVICE_CLASS_ENERGY,
|
||||||
],
|
],
|
||||||
"electricity_produced_off_peak_point": [
|
"electricity_produced_off_peak_point": [
|
||||||
"Current Produced Power (off peak)",
|
"Current Produced Power (off peak)",
|
||||||
|
@ -128,12 +129,12 @@ ENERGY_SENSOR_MAP = {
|
||||||
"electricity_produced_off_peak_cumulative": [
|
"electricity_produced_off_peak_cumulative": [
|
||||||
"Cumulative Produced Power (off peak)",
|
"Cumulative Produced Power (off peak)",
|
||||||
ENERGY_KILO_WATT_HOUR,
|
ENERGY_KILO_WATT_HOUR,
|
||||||
DEVICE_CLASS_POWER,
|
DEVICE_CLASS_ENERGY,
|
||||||
],
|
],
|
||||||
"electricity_produced_peak_cumulative": [
|
"electricity_produced_peak_cumulative": [
|
||||||
"Cumulative Produced Power",
|
"Cumulative Produced Power",
|
||||||
ENERGY_KILO_WATT_HOUR,
|
ENERGY_KILO_WATT_HOUR,
|
||||||
DEVICE_CLASS_POWER,
|
DEVICE_CLASS_ENERGY,
|
||||||
],
|
],
|
||||||
"gas_consumed_interval": [
|
"gas_consumed_interval": [
|
||||||
"Current Consumed Gas Interval",
|
"Current Consumed Gas Interval",
|
||||||
|
@ -145,7 +146,7 @@ ENERGY_SENSOR_MAP = {
|
||||||
"net_electricity_cumulative": [
|
"net_electricity_cumulative": [
|
||||||
"Cumulative net Power",
|
"Cumulative net Power",
|
||||||
ENERGY_KILO_WATT_HOUR,
|
ENERGY_KILO_WATT_HOUR,
|
||||||
DEVICE_CLASS_POWER,
|
DEVICE_CLASS_ENERGY,
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,9 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||||
|
|
||||||
await async_migrate_entries(hass, entry.entry_id, async_migrate_callback)
|
await async_migrate_entries(hass, entry.entry_id, async_migrate_callback)
|
||||||
|
|
||||||
websession = aiohttp_client.async_get_clientsession(hass)
|
# Tile's API uses cookies to identify a consumer; in order to allow for multiple
|
||||||
|
# instances of this config entry, we use a new session each time:
|
||||||
|
websession = aiohttp_client.async_create_clientsession(hass)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
client = await async_login(
|
client = await async_login(
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
"name": "Tile",
|
"name": "Tile",
|
||||||
"config_flow": true,
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/integrations/tile",
|
"documentation": "https://www.home-assistant.io/integrations/tile",
|
||||||
"requirements": ["pytile==5.2.3"],
|
"requirements": ["pytile==5.2.4"],
|
||||||
"codeowners": ["@bachya"],
|
"codeowners": ["@bachya"],
|
||||||
"iot_class": "cloud_polling"
|
"iot_class": "cloud_polling"
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ from yeelight.aio import AsyncBulb
|
||||||
|
|
||||||
from homeassistant import config_entries, exceptions
|
from homeassistant import config_entries, exceptions
|
||||||
from homeassistant.components.dhcp import IP_ADDRESS
|
from homeassistant.components.dhcp import IP_ADDRESS
|
||||||
|
from homeassistant.config_entries import ConfigEntryState
|
||||||
from homeassistant.const import CONF_DEVICE, CONF_HOST, CONF_ID, CONF_NAME
|
from homeassistant.const import CONF_DEVICE, CONF_HOST, CONF_ID, CONF_NAME
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
|
@ -66,18 +67,30 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
||||||
await self.async_set_unique_id(
|
await self.async_set_unique_id(
|
||||||
"{0:#0{1}x}".format(int(discovery_info["name"][-26:-18]), 18)
|
"{0:#0{1}x}".format(int(discovery_info["name"][-26:-18]), 18)
|
||||||
)
|
)
|
||||||
self._abort_if_unique_id_configured(
|
return await self._async_handle_discovery_with_unique_id()
|
||||||
updates={CONF_HOST: self._discovered_ip}, reload_on_update=False
|
|
||||||
)
|
|
||||||
return await self._async_handle_discovery()
|
|
||||||
|
|
||||||
async def async_step_ssdp(self, discovery_info):
|
async def async_step_ssdp(self, discovery_info):
|
||||||
"""Handle discovery from ssdp."""
|
"""Handle discovery from ssdp."""
|
||||||
self._discovered_ip = urlparse(discovery_info["location"]).hostname
|
self._discovered_ip = urlparse(discovery_info["location"]).hostname
|
||||||
await self.async_set_unique_id(discovery_info["id"])
|
await self.async_set_unique_id(discovery_info["id"])
|
||||||
self._abort_if_unique_id_configured(
|
return await self._async_handle_discovery_with_unique_id()
|
||||||
updates={CONF_HOST: self._discovered_ip}, reload_on_update=False
|
|
||||||
)
|
async def _async_handle_discovery_with_unique_id(self):
|
||||||
|
"""Handle any discovery with a unique id."""
|
||||||
|
for entry in self._async_current_entries():
|
||||||
|
if entry.unique_id != self.unique_id:
|
||||||
|
continue
|
||||||
|
reload = entry.state == ConfigEntryState.SETUP_RETRY
|
||||||
|
if entry.data[CONF_HOST] != self._discovered_ip:
|
||||||
|
self.hass.config_entries.async_update_entry(
|
||||||
|
entry, data={**entry.data, CONF_HOST: self._discovered_ip}
|
||||||
|
)
|
||||||
|
reload = True
|
||||||
|
if reload:
|
||||||
|
self.hass.async_create_task(
|
||||||
|
self.hass.config_entries.async_reload(entry.entry_id)
|
||||||
|
)
|
||||||
|
return self.async_abort(reason="already_configured")
|
||||||
return await self._async_handle_discovery()
|
return await self._async_handle_discovery()
|
||||||
|
|
||||||
async def _async_handle_discovery(self):
|
async def _async_handle_discovery(self):
|
||||||
|
@ -86,6 +99,7 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
||||||
for progress in self._async_in_progress():
|
for progress in self._async_in_progress():
|
||||||
if progress.get("context", {}).get(CONF_HOST) == self._discovered_ip:
|
if progress.get("context", {}).get(CONF_HOST) == self._discovered_ip:
|
||||||
return self.async_abort(reason="already_in_progress")
|
return self.async_abort(reason="already_in_progress")
|
||||||
|
self._async_abort_entries_match({CONF_HOST: self._discovered_ip})
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self._discovered_model = await self._async_try_connect(
|
self._discovered_model = await self._async_try_connect(
|
||||||
|
|
|
@ -5,7 +5,7 @@ from typing import Final
|
||||||
|
|
||||||
MAJOR_VERSION: Final = 2021
|
MAJOR_VERSION: Final = 2021
|
||||||
MINOR_VERSION: Final = 10
|
MINOR_VERSION: Final = 10
|
||||||
PATCH_VERSION: Final = "5"
|
PATCH_VERSION: Final = "6"
|
||||||
__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, 8, 0)
|
REQUIRED_PYTHON_VER: Final[tuple[int, int, int]] = (3, 8, 0)
|
||||||
|
|
|
@ -179,7 +179,7 @@ aiogithubapi==21.8.0
|
||||||
aioguardian==1.0.8
|
aioguardian==1.0.8
|
||||||
|
|
||||||
# homeassistant.components.harmony
|
# homeassistant.components.harmony
|
||||||
aioharmony==0.2.7
|
aioharmony==0.2.8
|
||||||
|
|
||||||
# homeassistant.components.homekit_controller
|
# homeassistant.components.homekit_controller
|
||||||
aiohomekit==0.6.3
|
aiohomekit==0.6.3
|
||||||
|
@ -415,7 +415,7 @@ blockchain==1.4.4
|
||||||
# bme680==1.0.5
|
# bme680==1.0.5
|
||||||
|
|
||||||
# homeassistant.components.bond
|
# homeassistant.components.bond
|
||||||
bond-api==0.1.13
|
bond-api==0.1.14
|
||||||
|
|
||||||
# homeassistant.components.bosch_shc
|
# homeassistant.components.bosch_shc
|
||||||
boschshcpy==0.2.19
|
boschshcpy==0.2.19
|
||||||
|
@ -1964,7 +1964,7 @@ python_opendata_transport==0.2.1
|
||||||
pythonegardia==1.0.40
|
pythonegardia==1.0.40
|
||||||
|
|
||||||
# homeassistant.components.tile
|
# homeassistant.components.tile
|
||||||
pytile==5.2.3
|
pytile==5.2.4
|
||||||
|
|
||||||
# homeassistant.components.touchline
|
# homeassistant.components.touchline
|
||||||
pytouchline==0.7
|
pytouchline==0.7
|
||||||
|
|
|
@ -118,7 +118,7 @@ aioflo==0.4.1
|
||||||
aioguardian==1.0.8
|
aioguardian==1.0.8
|
||||||
|
|
||||||
# homeassistant.components.harmony
|
# homeassistant.components.harmony
|
||||||
aioharmony==0.2.7
|
aioharmony==0.2.8
|
||||||
|
|
||||||
# homeassistant.components.homekit_controller
|
# homeassistant.components.homekit_controller
|
||||||
aiohomekit==0.6.3
|
aiohomekit==0.6.3
|
||||||
|
@ -254,7 +254,7 @@ blebox_uniapi==1.3.3
|
||||||
blinkpy==0.17.0
|
blinkpy==0.17.0
|
||||||
|
|
||||||
# homeassistant.components.bond
|
# homeassistant.components.bond
|
||||||
bond-api==0.1.13
|
bond-api==0.1.14
|
||||||
|
|
||||||
# homeassistant.components.bosch_shc
|
# homeassistant.components.bosch_shc
|
||||||
boschshcpy==0.2.19
|
boschshcpy==0.2.19
|
||||||
|
@ -1127,7 +1127,7 @@ python-twitch-client==0.6.0
|
||||||
python_awair==0.2.1
|
python_awair==0.2.1
|
||||||
|
|
||||||
# homeassistant.components.tile
|
# homeassistant.components.tile
|
||||||
pytile==5.2.3
|
pytile==5.2.4
|
||||||
|
|
||||||
# homeassistant.components.traccar
|
# homeassistant.components.traccar
|
||||||
pytraccar==0.9.0
|
pytraccar==0.9.0
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
"""Test the Logitech Harmony Hub config flow."""
|
"""Test the Logitech Harmony Hub config flow."""
|
||||||
from unittest.mock import AsyncMock, MagicMock, patch
|
from unittest.mock import AsyncMock, MagicMock, patch
|
||||||
|
|
||||||
|
import aiohttp
|
||||||
|
|
||||||
from homeassistant import config_entries, data_entry_flow, setup
|
from homeassistant import config_entries, data_entry_flow, setup
|
||||||
from homeassistant.components.harmony.config_flow import CannotConnect
|
from homeassistant.components.harmony.config_flow import CannotConnect
|
||||||
from homeassistant.components.harmony.const import DOMAIN, PREVIOUS_ACTIVE_ACTIVITY
|
from homeassistant.components.harmony.const import DOMAIN, PREVIOUS_ACTIVE_ACTIVITY
|
||||||
|
@ -50,11 +52,9 @@ async def test_form_ssdp(hass):
|
||||||
"""Test we get the form with ssdp source."""
|
"""Test we get the form with ssdp source."""
|
||||||
await setup.async_setup_component(hass, "persistent_notification", {})
|
await setup.async_setup_component(hass, "persistent_notification", {})
|
||||||
|
|
||||||
harmonyapi = _get_mock_harmonyapi(connect=True)
|
|
||||||
|
|
||||||
with patch(
|
with patch(
|
||||||
"homeassistant.components.harmony.util.HarmonyAPI",
|
"homeassistant.components.harmony.config_flow.HubConnector.get_remote_id",
|
||||||
return_value=harmonyapi,
|
return_value=1234,
|
||||||
):
|
):
|
||||||
result = await hass.config_entries.flow.async_init(
|
result = await hass.config_entries.flow.async_init(
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
|
@ -76,6 +76,8 @@ async def test_form_ssdp(hass):
|
||||||
assert progress[0]["flow_id"] == result["flow_id"]
|
assert progress[0]["flow_id"] == result["flow_id"]
|
||||||
assert progress[0]["context"]["confirm_only"] is True
|
assert progress[0]["context"]["confirm_only"] is True
|
||||||
|
|
||||||
|
harmonyapi = _get_mock_harmonyapi(connect=True)
|
||||||
|
|
||||||
with patch(
|
with patch(
|
||||||
"homeassistant.components.harmony.util.HarmonyAPI",
|
"homeassistant.components.harmony.util.HarmonyAPI",
|
||||||
return_value=harmonyapi,
|
return_value=harmonyapi,
|
||||||
|
@ -95,6 +97,25 @@ async def test_form_ssdp(hass):
|
||||||
assert len(mock_setup_entry.mock_calls) == 1
|
assert len(mock_setup_entry.mock_calls) == 1
|
||||||
|
|
||||||
|
|
||||||
|
async def test_form_ssdp_fails_to_get_remote_id(hass):
|
||||||
|
"""Test we abort if we cannot get the remote id."""
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.harmony.config_flow.HubConnector.get_remote_id",
|
||||||
|
side_effect=aiohttp.ClientError,
|
||||||
|
):
|
||||||
|
result = await hass.config_entries.flow.async_init(
|
||||||
|
DOMAIN,
|
||||||
|
context={"source": config_entries.SOURCE_SSDP},
|
||||||
|
data={
|
||||||
|
"friendlyName": "Harmony Hub",
|
||||||
|
"ssdp_location": "http://192.168.1.12:8088/description",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
assert result["type"] == "abort"
|
||||||
|
assert result["reason"] == "cannot_connect"
|
||||||
|
|
||||||
|
|
||||||
async def test_form_ssdp_aborts_before_checking_remoteid_if_host_known(hass):
|
async def test_form_ssdp_aborts_before_checking_remoteid_if_host_known(hass):
|
||||||
"""Test we abort without connecting if the host is already known."""
|
"""Test we abort without connecting if the host is already known."""
|
||||||
await setup.async_setup_component(hass, "persistent_notification", {})
|
await setup.async_setup_component(hass, "persistent_notification", {})
|
||||||
|
|
|
@ -502,6 +502,18 @@ async def test_discovered_by_dhcp_or_homekit(hass, source, data):
|
||||||
assert mock_async_setup.called
|
assert mock_async_setup.called
|
||||||
assert mock_async_setup_entry.called
|
assert mock_async_setup_entry.called
|
||||||
|
|
||||||
|
with _patch_discovery(
|
||||||
|
no_device=True
|
||||||
|
), _patch_discovery_timeout(), _patch_discovery_interval(), patch(
|
||||||
|
f"{MODULE_CONFIG_FLOW}.AsyncBulb", side_effect=CannotConnect
|
||||||
|
):
|
||||||
|
result3 = await hass.config_entries.flow.async_init(
|
||||||
|
DOMAIN, context={"source": source}, data=data
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert result3["type"] == RESULT_TYPE_ABORT
|
||||||
|
assert result3["reason"] == "already_configured"
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"source, data",
|
"source, data",
|
||||||
|
|
Loading…
Add table
Reference in a new issue