mirror of
https://github.com/home-assistant/core.git
synced 2025-07-27 07:07:28 +00:00
Merge pull request #34323 from home-assistant/rc
This commit is contained in:
commit
6e86cbf947
@ -2,7 +2,6 @@
|
|||||||
"domain": "broadlink",
|
"domain": "broadlink",
|
||||||
"name": "Broadlink",
|
"name": "Broadlink",
|
||||||
"documentation": "https://www.home-assistant.io/integrations/broadlink",
|
"documentation": "https://www.home-assistant.io/integrations/broadlink",
|
||||||
"requirements": ["broadlink==0.13.0"],
|
"requirements": ["broadlink==0.13.1"],
|
||||||
"dependencies": [],
|
|
||||||
"codeowners": ["@danielhiversen", "@felipediel"]
|
"codeowners": ["@danielhiversen", "@felipediel"]
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,8 @@ from homeassistant.const import (
|
|||||||
CONF_PASSWORD,
|
CONF_PASSWORD,
|
||||||
CONF_TEMPERATURE_UNIT,
|
CONF_TEMPERATURE_UNIT,
|
||||||
CONF_USERNAME,
|
CONF_USERNAME,
|
||||||
|
TEMP_CELSIUS,
|
||||||
|
TEMP_FAHRENHEIT,
|
||||||
)
|
)
|
||||||
from homeassistant.core import HomeAssistant, callback
|
from homeassistant.core import HomeAssistant, callback
|
||||||
from homeassistant.exceptions import ConfigEntryNotReady
|
from homeassistant.exceptions import ConfigEntryNotReady
|
||||||
@ -23,6 +25,8 @@ from homeassistant.helpers.entity import Entity
|
|||||||
from homeassistant.helpers.typing import ConfigType
|
from homeassistant.helpers.typing import ConfigType
|
||||||
|
|
||||||
from .const import (
|
from .const import (
|
||||||
|
BARE_TEMP_CELSIUS,
|
||||||
|
BARE_TEMP_FAHRENHEIT,
|
||||||
CONF_AREA,
|
CONF_AREA,
|
||||||
CONF_AUTO_CONFIGURE,
|
CONF_AUTO_CONFIGURE,
|
||||||
CONF_COUNTER,
|
CONF_COUNTER,
|
||||||
@ -119,7 +123,10 @@ DEVICE_SCHEMA = vol.Schema(
|
|||||||
vol.Optional(CONF_USERNAME, default=""): cv.string,
|
vol.Optional(CONF_USERNAME, default=""): cv.string,
|
||||||
vol.Optional(CONF_PASSWORD, default=""): cv.string,
|
vol.Optional(CONF_PASSWORD, default=""): cv.string,
|
||||||
vol.Optional(CONF_AUTO_CONFIGURE, default=False): cv.boolean,
|
vol.Optional(CONF_AUTO_CONFIGURE, default=False): cv.boolean,
|
||||||
vol.Optional(CONF_TEMPERATURE_UNIT, default="F"): cv.temperature_unit,
|
# cv.temperature_unit will mutate 'C' -> '°C' and 'F' -> '°F'
|
||||||
|
vol.Optional(
|
||||||
|
CONF_TEMPERATURE_UNIT, default=BARE_TEMP_FAHRENHEIT
|
||||||
|
): cv.temperature_unit,
|
||||||
vol.Optional(CONF_AREA, default={}): DEVICE_SCHEMA_SUBDOMAIN,
|
vol.Optional(CONF_AREA, default={}): DEVICE_SCHEMA_SUBDOMAIN,
|
||||||
vol.Optional(CONF_COUNTER, default={}): DEVICE_SCHEMA_SUBDOMAIN,
|
vol.Optional(CONF_COUNTER, default={}): DEVICE_SCHEMA_SUBDOMAIN,
|
||||||
vol.Optional(CONF_KEYPAD, default={}): DEVICE_SCHEMA_SUBDOMAIN,
|
vol.Optional(CONF_KEYPAD, default={}): DEVICE_SCHEMA_SUBDOMAIN,
|
||||||
@ -187,7 +194,11 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
|
|||||||
|
|
||||||
_LOGGER.debug("Setting up elkm1 %s", conf["host"])
|
_LOGGER.debug("Setting up elkm1 %s", conf["host"])
|
||||||
|
|
||||||
config = {"temperature_unit": conf[CONF_TEMPERATURE_UNIT]}
|
temperature_unit = TEMP_FAHRENHEIT
|
||||||
|
if conf[CONF_TEMPERATURE_UNIT] in (BARE_TEMP_CELSIUS, TEMP_CELSIUS):
|
||||||
|
temperature_unit = TEMP_CELSIUS
|
||||||
|
|
||||||
|
config = {"temperature_unit": temperature_unit}
|
||||||
|
|
||||||
if not conf[CONF_AUTO_CONFIGURE]:
|
if not conf[CONF_AUTO_CONFIGURE]:
|
||||||
# With elkm1-lib==0.7.16 and later auto configure is available
|
# With elkm1-lib==0.7.16 and later auto configure is available
|
||||||
|
@ -14,7 +14,7 @@ from homeassistant.components.climate.const import (
|
|||||||
SUPPORT_FAN_MODE,
|
SUPPORT_FAN_MODE,
|
||||||
SUPPORT_TARGET_TEMPERATURE_RANGE,
|
SUPPORT_TARGET_TEMPERATURE_RANGE,
|
||||||
)
|
)
|
||||||
from homeassistant.const import PRECISION_WHOLE, STATE_ON, TEMP_CELSIUS, TEMP_FAHRENHEIT
|
from homeassistant.const import PRECISION_WHOLE, STATE_ON
|
||||||
|
|
||||||
from . import ElkEntity, create_elk_entities
|
from . import ElkEntity, create_elk_entities
|
||||||
from .const import DOMAIN
|
from .const import DOMAIN
|
||||||
@ -55,7 +55,7 @@ class ElkThermostat(ElkEntity, ClimateDevice):
|
|||||||
@property
|
@property
|
||||||
def temperature_unit(self):
|
def temperature_unit(self):
|
||||||
"""Return the temperature unit."""
|
"""Return the temperature unit."""
|
||||||
return TEMP_FAHRENHEIT if self._temperature_unit == "F" else TEMP_CELSIUS
|
return self._temperature_unit
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def current_temperature(self):
|
def current_temperature(self):
|
||||||
|
@ -13,6 +13,8 @@ from homeassistant.const import (
|
|||||||
CONF_PROTOCOL,
|
CONF_PROTOCOL,
|
||||||
CONF_TEMPERATURE_UNIT,
|
CONF_TEMPERATURE_UNIT,
|
||||||
CONF_USERNAME,
|
CONF_USERNAME,
|
||||||
|
TEMP_CELSIUS,
|
||||||
|
TEMP_FAHRENHEIT,
|
||||||
)
|
)
|
||||||
from homeassistant.util import slugify
|
from homeassistant.util import slugify
|
||||||
|
|
||||||
@ -33,7 +35,9 @@ DATA_SCHEMA = vol.Schema(
|
|||||||
vol.Optional(CONF_USERNAME, default=""): str,
|
vol.Optional(CONF_USERNAME, default=""): str,
|
||||||
vol.Optional(CONF_PASSWORD, default=""): str,
|
vol.Optional(CONF_PASSWORD, default=""): str,
|
||||||
vol.Optional(CONF_PREFIX, default=""): str,
|
vol.Optional(CONF_PREFIX, default=""): str,
|
||||||
vol.Optional(CONF_TEMPERATURE_UNIT, default="F"): vol.In(["F", "C"]),
|
vol.Optional(CONF_TEMPERATURE_UNIT, default=TEMP_FAHRENHEIT): vol.In(
|
||||||
|
[TEMP_FAHRENHEIT, TEMP_CELSIUS]
|
||||||
|
),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -18,6 +18,9 @@ CONF_ZONE = "zone"
|
|||||||
CONF_PREFIX = "prefix"
|
CONF_PREFIX = "prefix"
|
||||||
|
|
||||||
|
|
||||||
|
BARE_TEMP_FAHRENHEIT = "F"
|
||||||
|
BARE_TEMP_CELSIUS = "C"
|
||||||
|
|
||||||
ELK_ELEMENTS = {
|
ELK_ELEMENTS = {
|
||||||
CONF_AREA: Max.AREAS.value,
|
CONF_AREA: Max.AREAS.value,
|
||||||
CONF_COUNTER: Max.COUNTERS.value,
|
CONF_COUNTER: Max.COUNTERS.value,
|
||||||
|
@ -357,7 +357,7 @@ class KefMediaPlayer(MediaPlayerDevice):
|
|||||||
"""Send next track command."""
|
"""Send next track command."""
|
||||||
await self._speaker.next_track()
|
await self._speaker.next_track()
|
||||||
|
|
||||||
async def update_dsp(self) -> None:
|
async def update_dsp(self, _=None) -> None:
|
||||||
"""Update the DSP settings."""
|
"""Update the DSP settings."""
|
||||||
if self._speaker_type == "LS50" and self._state == STATE_OFF:
|
if self._speaker_type == "LS50" and self._state == STATE_OFF:
|
||||||
# The LSX is able to respond when off the LS50 has to be on.
|
# The LSX is able to respond when off the LS50 has to be on.
|
||||||
|
@ -58,10 +58,15 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
|
|||||||
|
|
||||||
_LOGGER.debug("NUT Sensors Available: %s", status)
|
_LOGGER.debug("NUT Sensors Available: %s", status)
|
||||||
|
|
||||||
|
unique_id = _unique_id_from_status(status)
|
||||||
|
|
||||||
|
if unique_id is None:
|
||||||
|
unique_id = entry.entry_id
|
||||||
|
|
||||||
hass.data[DOMAIN][entry.entry_id] = {
|
hass.data[DOMAIN][entry.entry_id] = {
|
||||||
PYNUT_DATA: data,
|
PYNUT_DATA: data,
|
||||||
PYNUT_STATUS: status,
|
PYNUT_STATUS: status,
|
||||||
PYNUT_UNIQUE_ID: _unique_id_from_status(status),
|
PYNUT_UNIQUE_ID: unique_id,
|
||||||
PYNUT_MANUFACTURER: _manufacturer_from_status(status),
|
PYNUT_MANUFACTURER: _manufacturer_from_status(status),
|
||||||
PYNUT_MODEL: _model_from_status(status),
|
PYNUT_MODEL: _model_from_status(status),
|
||||||
PYNUT_FIRMWARE: _firmware_from_status(status),
|
PYNUT_FIRMWARE: _firmware_from_status(status),
|
||||||
|
@ -419,7 +419,7 @@ class SonosEntity(MediaPlayerDevice):
|
|||||||
if self._status in ("PAUSED_PLAYBACK", "STOPPED",):
|
if self._status in ("PAUSED_PLAYBACK", "STOPPED",):
|
||||||
# Sonos can consider itself "paused" but without having media loaded
|
# Sonos can consider itself "paused" but without having media loaded
|
||||||
# (happens if playing Spotify and via Spotify app you pick another device to play on)
|
# (happens if playing Spotify and via Spotify app you pick another device to play on)
|
||||||
if self._media_title is None:
|
if self.media_title is None:
|
||||||
return STATE_IDLE
|
return STATE_IDLE
|
||||||
return STATE_PAUSED
|
return STATE_PAUSED
|
||||||
if self._status in ("PLAYING", "TRANSITIONING"):
|
if self._status in ("PLAYING", "TRANSITIONING"):
|
||||||
@ -614,12 +614,19 @@ class SonosEntity(MediaPlayerDevice):
|
|||||||
except (TypeError, KeyError, AttributeError):
|
except (TypeError, KeyError, AttributeError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# Radios without tagging can have part of the radio URI as title.
|
# Non-playing radios will not have a current title. Radios without tagging
|
||||||
# Non-playing radios will not have a current title. In these cases we
|
# can have part of the radio URI as title. In these cases we try to use the
|
||||||
# try to use the radio name instead.
|
# radio name instead.
|
||||||
try:
|
try:
|
||||||
if self._media_title in self._uri or self.state != STATE_PLAYING:
|
uri_meta_data = variables["enqueued_transport_uri_meta_data"]
|
||||||
self._media_title = variables["enqueued_transport_uri_meta_data"].title
|
if isinstance(
|
||||||
|
uri_meta_data, pysonos.data_structures.DidlAudioBroadcast
|
||||||
|
) and (
|
||||||
|
self.state != STATE_PLAYING
|
||||||
|
or self.soco.is_radio_uri(self._media_title)
|
||||||
|
or self._media_title in self._uri
|
||||||
|
):
|
||||||
|
self._media_title = uri_meta_data.title
|
||||||
except (TypeError, KeyError, AttributeError):
|
except (TypeError, KeyError, AttributeError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -8,7 +8,12 @@ import voluptuous as vol
|
|||||||
|
|
||||||
from homeassistant import config_entries
|
from homeassistant import config_entries
|
||||||
from homeassistant.components.media_player import DEVICE_CLASS_SPEAKER, DEVICE_CLASS_TV
|
from homeassistant.components.media_player import DEVICE_CLASS_SPEAKER, DEVICE_CLASS_TV
|
||||||
from homeassistant.config_entries import SOURCE_IMPORT, SOURCE_ZEROCONF, ConfigEntry
|
from homeassistant.config_entries import (
|
||||||
|
SOURCE_IGNORE,
|
||||||
|
SOURCE_IMPORT,
|
||||||
|
SOURCE_ZEROCONF,
|
||||||
|
ConfigEntry,
|
||||||
|
)
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
CONF_ACCESS_TOKEN,
|
CONF_ACCESS_TOKEN,
|
||||||
CONF_DEVICE_CLASS,
|
CONF_DEVICE_CLASS,
|
||||||
@ -198,8 +203,13 @@ class VizioConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
|
|
||||||
# Check if new config entry matches any existing config entries
|
# Check if new config entry matches any existing config entries
|
||||||
for entry in self.hass.config_entries.async_entries(DOMAIN):
|
for entry in self.hass.config_entries.async_entries(DOMAIN):
|
||||||
|
# If source is ignore bypass host and name check and continue through loop
|
||||||
|
if entry.source == SOURCE_IGNORE:
|
||||||
|
continue
|
||||||
|
|
||||||
if _host_is_same(entry.data[CONF_HOST], user_input[CONF_HOST]):
|
if _host_is_same(entry.data[CONF_HOST], user_input[CONF_HOST]):
|
||||||
errors[CONF_HOST] = "host_exists"
|
errors[CONF_HOST] = "host_exists"
|
||||||
|
|
||||||
if entry.data[CONF_NAME] == user_input[CONF_NAME]:
|
if entry.data[CONF_NAME] == user_input[CONF_NAME]:
|
||||||
errors[CONF_NAME] = "name_exists"
|
errors[CONF_NAME] = "name_exists"
|
||||||
|
|
||||||
@ -270,6 +280,10 @@ class VizioConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
"""Import a config entry from configuration.yaml."""
|
"""Import a config entry from configuration.yaml."""
|
||||||
# Check if new config entry matches any existing config entries
|
# Check if new config entry matches any existing config entries
|
||||||
for entry in self.hass.config_entries.async_entries(DOMAIN):
|
for entry in self.hass.config_entries.async_entries(DOMAIN):
|
||||||
|
# If source is ignore bypass host check and continue through loop
|
||||||
|
if entry.source == SOURCE_IGNORE:
|
||||||
|
continue
|
||||||
|
|
||||||
if _host_is_same(entry.data[CONF_HOST], import_config[CONF_HOST]):
|
if _host_is_same(entry.data[CONF_HOST], import_config[CONF_HOST]):
|
||||||
updated_options = {}
|
updated_options = {}
|
||||||
updated_data = {}
|
updated_data = {}
|
||||||
@ -327,6 +341,7 @@ class VizioConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
await self.async_set_unique_id(
|
await self.async_set_unique_id(
|
||||||
unique_id=discovery_info[CONF_HOST].split(":")[0], raise_on_progress=True
|
unique_id=discovery_info[CONF_HOST].split(":")[0], raise_on_progress=True
|
||||||
)
|
)
|
||||||
|
self._abort_if_unique_id_configured()
|
||||||
|
|
||||||
discovery_info[
|
discovery_info[
|
||||||
CONF_HOST
|
CONF_HOST
|
||||||
@ -334,6 +349,10 @@ class VizioConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
|
|
||||||
# Check if new config entry matches any existing config entries and abort if so
|
# Check if new config entry matches any existing config entries and abort if so
|
||||||
for entry in self.hass.config_entries.async_entries(DOMAIN):
|
for entry in self.hass.config_entries.async_entries(DOMAIN):
|
||||||
|
# If source is ignore bypass host check and continue through loop
|
||||||
|
if entry.source == SOURCE_IGNORE:
|
||||||
|
continue
|
||||||
|
|
||||||
if _host_is_same(entry.data[CONF_HOST], discovery_info[CONF_HOST]):
|
if _host_is_same(entry.data[CONF_HOST], discovery_info[CONF_HOST]):
|
||||||
return self.async_abort(reason="already_setup")
|
return self.async_abort(reason="already_setup")
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
"""Constants used by Home Assistant components."""
|
"""Constants used by Home Assistant components."""
|
||||||
MAJOR_VERSION = 0
|
MAJOR_VERSION = 0
|
||||||
MINOR_VERSION = 108
|
MINOR_VERSION = 108
|
||||||
PATCH_VERSION = "5"
|
PATCH_VERSION = "6"
|
||||||
__short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}"
|
__short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}"
|
||||||
__version__ = f"{__short_version__}.{PATCH_VERSION}"
|
__version__ = f"{__short_version__}.{PATCH_VERSION}"
|
||||||
REQUIRED_PYTHON_VER = (3, 7, 0)
|
REQUIRED_PYTHON_VER = (3, 7, 0)
|
||||||
|
@ -163,6 +163,7 @@ class DataUpdateCoordinator:
|
|||||||
self.name,
|
self.name,
|
||||||
monotonic() - start,
|
monotonic() - start,
|
||||||
)
|
)
|
||||||
|
if self._listeners:
|
||||||
self._schedule_refresh()
|
self._schedule_refresh()
|
||||||
|
|
||||||
for update_callback in self._listeners:
|
for update_callback in self._listeners:
|
||||||
|
@ -355,7 +355,7 @@ boto3==1.9.252
|
|||||||
bravia-tv==1.0.1
|
bravia-tv==1.0.1
|
||||||
|
|
||||||
# homeassistant.components.broadlink
|
# homeassistant.components.broadlink
|
||||||
broadlink==0.13.0
|
broadlink==0.13.1
|
||||||
|
|
||||||
# homeassistant.components.brother
|
# homeassistant.components.brother
|
||||||
brother==0.1.11
|
brother==0.1.11
|
||||||
|
@ -137,7 +137,7 @@ bellows-homeassistant==0.15.2
|
|||||||
bomradarloop==0.1.4
|
bomradarloop==0.1.4
|
||||||
|
|
||||||
# homeassistant.components.broadlink
|
# homeassistant.components.broadlink
|
||||||
broadlink==0.13.0
|
broadlink==0.13.1
|
||||||
|
|
||||||
# homeassistant.components.brother
|
# homeassistant.components.brother
|
||||||
brother==0.1.11
|
brother==0.1.11
|
||||||
|
@ -39,7 +39,7 @@ async def test_form_user_with_secure_elk(hass):
|
|||||||
"address": "1.2.3.4",
|
"address": "1.2.3.4",
|
||||||
"username": "test-username",
|
"username": "test-username",
|
||||||
"password": "test-password",
|
"password": "test-password",
|
||||||
"temperature_unit": "F",
|
"temperature_unit": "°F",
|
||||||
"prefix": "",
|
"prefix": "",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -51,7 +51,7 @@ async def test_form_user_with_secure_elk(hass):
|
|||||||
"host": "elks://1.2.3.4",
|
"host": "elks://1.2.3.4",
|
||||||
"password": "test-password",
|
"password": "test-password",
|
||||||
"prefix": "",
|
"prefix": "",
|
||||||
"temperature_unit": "F",
|
"temperature_unit": "°F",
|
||||||
"username": "test-username",
|
"username": "test-username",
|
||||||
}
|
}
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
@ -82,7 +82,7 @@ async def test_form_user_with_non_secure_elk(hass):
|
|||||||
{
|
{
|
||||||
"protocol": "non-secure",
|
"protocol": "non-secure",
|
||||||
"address": "1.2.3.4",
|
"address": "1.2.3.4",
|
||||||
"temperature_unit": "F",
|
"temperature_unit": "°F",
|
||||||
"prefix": "guest_house",
|
"prefix": "guest_house",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -95,7 +95,7 @@ async def test_form_user_with_non_secure_elk(hass):
|
|||||||
"prefix": "guest_house",
|
"prefix": "guest_house",
|
||||||
"username": "",
|
"username": "",
|
||||||
"password": "",
|
"password": "",
|
||||||
"temperature_unit": "F",
|
"temperature_unit": "°F",
|
||||||
}
|
}
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert len(mock_setup.mock_calls) == 1
|
assert len(mock_setup.mock_calls) == 1
|
||||||
@ -125,7 +125,7 @@ async def test_form_user_with_serial_elk(hass):
|
|||||||
{
|
{
|
||||||
"protocol": "serial",
|
"protocol": "serial",
|
||||||
"address": "/dev/ttyS0:115200",
|
"address": "/dev/ttyS0:115200",
|
||||||
"temperature_unit": "F",
|
"temperature_unit": "°C",
|
||||||
"prefix": "",
|
"prefix": "",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -138,7 +138,7 @@ async def test_form_user_with_serial_elk(hass):
|
|||||||
"prefix": "",
|
"prefix": "",
|
||||||
"username": "",
|
"username": "",
|
||||||
"password": "",
|
"password": "",
|
||||||
"temperature_unit": "F",
|
"temperature_unit": "°C",
|
||||||
}
|
}
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert len(mock_setup.mock_calls) == 1
|
assert len(mock_setup.mock_calls) == 1
|
||||||
@ -166,7 +166,7 @@ async def test_form_cannot_connect(hass):
|
|||||||
"address": "1.2.3.4",
|
"address": "1.2.3.4",
|
||||||
"username": "test-username",
|
"username": "test-username",
|
||||||
"password": "test-password",
|
"password": "test-password",
|
||||||
"temperature_unit": "F",
|
"temperature_unit": "°F",
|
||||||
"prefix": "",
|
"prefix": "",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -193,7 +193,7 @@ async def test_form_invalid_auth(hass):
|
|||||||
"address": "1.2.3.4",
|
"address": "1.2.3.4",
|
||||||
"username": "test-username",
|
"username": "test-username",
|
||||||
"password": "test-password",
|
"password": "test-password",
|
||||||
"temperature_unit": "F",
|
"temperature_unit": "°F",
|
||||||
"prefix": "",
|
"prefix": "",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -174,6 +174,7 @@ MOCK_INCLUDE_APPS = {
|
|||||||
CONF_INCLUDE_OR_EXCLUDE: CONF_INCLUDE.title(),
|
CONF_INCLUDE_OR_EXCLUDE: CONF_INCLUDE.title(),
|
||||||
CONF_APPS_TO_INCLUDE_OR_EXCLUDE: [CURRENT_APP],
|
CONF_APPS_TO_INCLUDE_OR_EXCLUDE: [CURRENT_APP],
|
||||||
}
|
}
|
||||||
|
|
||||||
MOCK_INCLUDE_NO_APPS = {
|
MOCK_INCLUDE_NO_APPS = {
|
||||||
CONF_INCLUDE_OR_EXCLUDE: CONF_INCLUDE.title(),
|
CONF_INCLUDE_OR_EXCLUDE: CONF_INCLUDE.title(),
|
||||||
CONF_APPS_TO_INCLUDE_OR_EXCLUDE: [],
|
CONF_APPS_TO_INCLUDE_OR_EXCLUDE: [],
|
||||||
|
@ -17,7 +17,12 @@ from homeassistant.components.vizio.const import (
|
|||||||
DOMAIN,
|
DOMAIN,
|
||||||
VIZIO_SCHEMA,
|
VIZIO_SCHEMA,
|
||||||
)
|
)
|
||||||
from homeassistant.config_entries import SOURCE_IMPORT, SOURCE_USER, SOURCE_ZEROCONF
|
from homeassistant.config_entries import (
|
||||||
|
SOURCE_IGNORE,
|
||||||
|
SOURCE_IMPORT,
|
||||||
|
SOURCE_USER,
|
||||||
|
SOURCE_ZEROCONF,
|
||||||
|
)
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
CONF_ACCESS_TOKEN,
|
CONF_ACCESS_TOKEN,
|
||||||
CONF_DEVICE_CLASS,
|
CONF_DEVICE_CLASS,
|
||||||
@ -46,6 +51,7 @@ from .const import (
|
|||||||
NAME2,
|
NAME2,
|
||||||
UNIQUE_ID,
|
UNIQUE_ID,
|
||||||
VOLUME_STEP,
|
VOLUME_STEP,
|
||||||
|
ZEROCONF_HOST,
|
||||||
)
|
)
|
||||||
|
|
||||||
from tests.common import MockConfigEntry
|
from tests.common import MockConfigEntry
|
||||||
@ -383,6 +389,26 @@ async def test_user_invalid_pin(
|
|||||||
assert result["errors"] == {CONF_PIN: "complete_pairing_failed"}
|
assert result["errors"] == {CONF_PIN: "complete_pairing_failed"}
|
||||||
|
|
||||||
|
|
||||||
|
async def test_user_ignore(
|
||||||
|
hass: HomeAssistantType,
|
||||||
|
vizio_connect: pytest.fixture,
|
||||||
|
vizio_bypass_setup: pytest.fixture,
|
||||||
|
) -> None:
|
||||||
|
"""Test user config flow doesn't throw an error when there's an existing ignored source."""
|
||||||
|
entry = MockConfigEntry(
|
||||||
|
domain=DOMAIN,
|
||||||
|
data=MOCK_SPEAKER_CONFIG,
|
||||||
|
options={CONF_VOLUME_STEP: VOLUME_STEP},
|
||||||
|
source=SOURCE_IGNORE,
|
||||||
|
)
|
||||||
|
entry.add_to_hass(hass)
|
||||||
|
|
||||||
|
result = await hass.config_entries.flow.async_init(
|
||||||
|
DOMAIN, context={"source": SOURCE_USER}, data=MOCK_SPEAKER_CONFIG
|
||||||
|
)
|
||||||
|
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
|
||||||
|
|
||||||
|
|
||||||
async def test_import_flow_minimum_fields(
|
async def test_import_flow_minimum_fields(
|
||||||
hass: HomeAssistantType,
|
hass: HomeAssistantType,
|
||||||
vizio_connect: pytest.fixture,
|
vizio_connect: pytest.fixture,
|
||||||
@ -679,6 +705,29 @@ async def test_import_error(
|
|||||||
assert len(vizio_log_list) == 1
|
assert len(vizio_log_list) == 1
|
||||||
|
|
||||||
|
|
||||||
|
async def test_import_ignore(
|
||||||
|
hass: HomeAssistantType,
|
||||||
|
vizio_connect: pytest.fixture,
|
||||||
|
vizio_bypass_setup: pytest.fixture,
|
||||||
|
) -> None:
|
||||||
|
"""Test import config flow doesn't throw an error when there's an existing ignored source."""
|
||||||
|
entry = MockConfigEntry(
|
||||||
|
domain=DOMAIN,
|
||||||
|
data=MOCK_SPEAKER_CONFIG,
|
||||||
|
options={CONF_VOLUME_STEP: VOLUME_STEP},
|
||||||
|
source=SOURCE_IGNORE,
|
||||||
|
)
|
||||||
|
entry.add_to_hass(hass)
|
||||||
|
|
||||||
|
result = await hass.config_entries.flow.async_init(
|
||||||
|
DOMAIN,
|
||||||
|
context={"source": SOURCE_IMPORT},
|
||||||
|
data=vol.Schema(VIZIO_SCHEMA)(MOCK_SPEAKER_CONFIG),
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
|
||||||
|
|
||||||
|
|
||||||
async def test_zeroconf_flow(
|
async def test_zeroconf_flow(
|
||||||
hass: HomeAssistantType,
|
hass: HomeAssistantType,
|
||||||
vizio_connect: pytest.fixture,
|
vizio_connect: pytest.fixture,
|
||||||
@ -756,3 +805,51 @@ async def test_zeroconf_dupe_fail(
|
|||||||
# Flow should abort because device is already setup
|
# Flow should abort because device is already setup
|
||||||
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
|
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
|
||||||
assert result["reason"] == "already_in_progress"
|
assert result["reason"] == "already_in_progress"
|
||||||
|
|
||||||
|
|
||||||
|
async def test_zeroconf_ignore(
|
||||||
|
hass: HomeAssistantType,
|
||||||
|
vizio_connect: pytest.fixture,
|
||||||
|
vizio_bypass_setup: pytest.fixture,
|
||||||
|
vizio_guess_device_type: pytest.fixture,
|
||||||
|
) -> None:
|
||||||
|
"""Test zeroconf discovery doesn't throw an error when there's an existing ignored source."""
|
||||||
|
entry = MockConfigEntry(
|
||||||
|
domain=DOMAIN,
|
||||||
|
data=MOCK_SPEAKER_CONFIG,
|
||||||
|
options={CONF_VOLUME_STEP: VOLUME_STEP},
|
||||||
|
source=SOURCE_IGNORE,
|
||||||
|
)
|
||||||
|
entry.add_to_hass(hass)
|
||||||
|
|
||||||
|
discovery_info = MOCK_ZEROCONF_SERVICE_INFO.copy()
|
||||||
|
result = await hass.config_entries.flow.async_init(
|
||||||
|
DOMAIN, context={"source": SOURCE_ZEROCONF}, data=discovery_info
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
|
|
||||||
|
|
||||||
|
async def test_zeroconf_abort_when_ignored(
|
||||||
|
hass: HomeAssistantType,
|
||||||
|
vizio_connect: pytest.fixture,
|
||||||
|
vizio_bypass_setup: pytest.fixture,
|
||||||
|
vizio_guess_device_type: pytest.fixture,
|
||||||
|
) -> None:
|
||||||
|
"""Test zeroconf discovery aborts when the same host has been ignored."""
|
||||||
|
entry = MockConfigEntry(
|
||||||
|
domain=DOMAIN,
|
||||||
|
data=MOCK_SPEAKER_CONFIG,
|
||||||
|
options={CONF_VOLUME_STEP: VOLUME_STEP},
|
||||||
|
source=SOURCE_IGNORE,
|
||||||
|
unique_id=ZEROCONF_HOST,
|
||||||
|
)
|
||||||
|
entry.add_to_hass(hass)
|
||||||
|
|
||||||
|
discovery_info = MOCK_ZEROCONF_SERVICE_INFO.copy()
|
||||||
|
result = await hass.config_entries.flow.async_init(
|
||||||
|
DOMAIN, context={"source": SOURCE_ZEROCONF}, data=discovery_info
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
|
||||||
|
assert result["reason"] == "already_configured"
|
||||||
|
@ -40,6 +40,8 @@ async def test_async_refresh(crd):
|
|||||||
await crd.async_refresh()
|
await crd.async_refresh()
|
||||||
assert crd.data == 1
|
assert crd.data == 1
|
||||||
assert crd.last_update_success is True
|
assert crd.last_update_success is True
|
||||||
|
# Make sure we didn't schedule a refresh because we have 0 listeners
|
||||||
|
assert crd._unsub_refresh is None
|
||||||
|
|
||||||
updates = []
|
updates = []
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user