mirror of
https://github.com/home-assistant/core.git
synced 2025-07-29 08:07:45 +00:00
2023.5.1 (#92513)
This commit is contained in:
commit
bce18bf61a
@ -18,7 +18,7 @@
|
|||||||
"bleak==0.20.2",
|
"bleak==0.20.2",
|
||||||
"bleak-retry-connector==3.0.2",
|
"bleak-retry-connector==3.0.2",
|
||||||
"bluetooth-adapters==0.15.3",
|
"bluetooth-adapters==0.15.3",
|
||||||
"bluetooth-auto-recovery==1.1.1",
|
"bluetooth-auto-recovery==1.1.2",
|
||||||
"bluetooth-data-tools==0.4.0",
|
"bluetooth-data-tools==0.4.0",
|
||||||
"dbus-fast==1.85.0"
|
"dbus-fast==1.85.0"
|
||||||
]
|
]
|
||||||
|
@ -24,7 +24,6 @@ from homeassistant.components.binary_sensor import BinarySensorDeviceClass
|
|||||||
from homeassistant.components.homeassistant.exposed_entities import (
|
from homeassistant.components.homeassistant.exposed_entities import (
|
||||||
async_expose_entity,
|
async_expose_entity,
|
||||||
async_get_assistant_settings,
|
async_get_assistant_settings,
|
||||||
async_get_entity_settings,
|
|
||||||
async_listen_entity_updates,
|
async_listen_entity_updates,
|
||||||
async_should_expose,
|
async_should_expose,
|
||||||
)
|
)
|
||||||
@ -201,10 +200,6 @@ class CloudAlexaConfig(alexa_config.AbstractConfig):
|
|||||||
return
|
return
|
||||||
|
|
||||||
for state in self.hass.states.async_all():
|
for state in self.hass.states.async_all():
|
||||||
with suppress(HomeAssistantError):
|
|
||||||
entity_settings = async_get_entity_settings(self.hass, state.entity_id)
|
|
||||||
if CLOUD_ALEXA in entity_settings:
|
|
||||||
continue
|
|
||||||
async_expose_entity(
|
async_expose_entity(
|
||||||
self.hass,
|
self.hass,
|
||||||
CLOUD_ALEXA,
|
CLOUD_ALEXA,
|
||||||
@ -212,10 +207,6 @@ class CloudAlexaConfig(alexa_config.AbstractConfig):
|
|||||||
self._should_expose_legacy(state.entity_id),
|
self._should_expose_legacy(state.entity_id),
|
||||||
)
|
)
|
||||||
for entity_id in self._prefs.alexa_entity_configs:
|
for entity_id in self._prefs.alexa_entity_configs:
|
||||||
with suppress(HomeAssistantError):
|
|
||||||
entity_settings = async_get_entity_settings(self.hass, entity_id)
|
|
||||||
if CLOUD_ALEXA in entity_settings:
|
|
||||||
continue
|
|
||||||
async_expose_entity(
|
async_expose_entity(
|
||||||
self.hass,
|
self.hass,
|
||||||
CLOUD_ALEXA,
|
CLOUD_ALEXA,
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
"""Google config for Cloud."""
|
"""Google config for Cloud."""
|
||||||
import asyncio
|
import asyncio
|
||||||
from contextlib import suppress
|
|
||||||
from http import HTTPStatus
|
from http import HTTPStatus
|
||||||
import logging
|
import logging
|
||||||
from typing import Any
|
from typing import Any
|
||||||
@ -178,10 +177,6 @@ class CloudGoogleConfig(AbstractConfig):
|
|||||||
|
|
||||||
for state in self.hass.states.async_all():
|
for state in self.hass.states.async_all():
|
||||||
entity_id = state.entity_id
|
entity_id = state.entity_id
|
||||||
with suppress(HomeAssistantError):
|
|
||||||
entity_settings = async_get_entity_settings(self.hass, entity_id)
|
|
||||||
if CLOUD_GOOGLE in entity_settings:
|
|
||||||
continue
|
|
||||||
async_expose_entity(
|
async_expose_entity(
|
||||||
self.hass,
|
self.hass,
|
||||||
CLOUD_GOOGLE,
|
CLOUD_GOOGLE,
|
||||||
@ -197,10 +192,6 @@ class CloudGoogleConfig(AbstractConfig):
|
|||||||
_2fa_disabled,
|
_2fa_disabled,
|
||||||
)
|
)
|
||||||
for entity_id in self._prefs.google_entity_configs:
|
for entity_id in self._prefs.google_entity_configs:
|
||||||
with suppress(HomeAssistantError):
|
|
||||||
entity_settings = async_get_entity_settings(self.hass, entity_id)
|
|
||||||
if CLOUD_GOOGLE in entity_settings:
|
|
||||||
continue
|
|
||||||
async_expose_entity(
|
async_expose_entity(
|
||||||
self.hass,
|
self.hass,
|
||||||
CLOUD_GOOGLE,
|
CLOUD_GOOGLE,
|
||||||
|
@ -20,5 +20,5 @@
|
|||||||
"documentation": "https://www.home-assistant.io/integrations/frontend",
|
"documentation": "https://www.home-assistant.io/integrations/frontend",
|
||||||
"integration_type": "system",
|
"integration_type": "system",
|
||||||
"quality_scale": "internal",
|
"quality_scale": "internal",
|
||||||
"requirements": ["home-assistant-frontend==20230503.1"]
|
"requirements": ["home-assistant-frontend==20230503.2"]
|
||||||
}
|
}
|
||||||
|
@ -205,13 +205,20 @@ class LIFXUpdateCoordinator(DataUpdateCoordinator[None]):
|
|||||||
methods, DEFAULT_ATTEMPTS, OVERALL_TIMEOUT
|
methods, DEFAULT_ATTEMPTS, OVERALL_TIMEOUT
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def get_number_of_zones(self) -> int:
|
||||||
|
"""Return the number of zones.
|
||||||
|
|
||||||
|
If the number of zones is not yet populated, return 0
|
||||||
|
"""
|
||||||
|
return len(self.device.color_zones) if self.device.color_zones else 0
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _async_build_color_zones_update_requests(self) -> list[Callable]:
|
def _async_build_color_zones_update_requests(self) -> list[Callable]:
|
||||||
"""Build a color zones update request."""
|
"""Build a color zones update request."""
|
||||||
device = self.device
|
device = self.device
|
||||||
return [
|
return [
|
||||||
partial(device.get_color_zones, start_index=zone)
|
partial(device.get_color_zones, start_index=zone)
|
||||||
for zone in range(0, len(device.color_zones), 8)
|
for zone in range(0, self.get_number_of_zones(), 8)
|
||||||
]
|
]
|
||||||
|
|
||||||
async def _async_update_data(self) -> None:
|
async def _async_update_data(self) -> None:
|
||||||
@ -224,7 +231,7 @@ class LIFXUpdateCoordinator(DataUpdateCoordinator[None]):
|
|||||||
):
|
):
|
||||||
await self._async_populate_device_info()
|
await self._async_populate_device_info()
|
||||||
|
|
||||||
num_zones = len(device.color_zones) if device.color_zones is not None else 0
|
num_zones = self.get_number_of_zones()
|
||||||
features = lifx_features(self.device)
|
features = lifx_features(self.device)
|
||||||
is_extended_multizone = features["extended_multizone"]
|
is_extended_multizone = features["extended_multizone"]
|
||||||
is_legacy_multizone = not is_extended_multizone and features["multizone"]
|
is_legacy_multizone = not is_extended_multizone and features["multizone"]
|
||||||
@ -256,7 +263,7 @@ class LIFXUpdateCoordinator(DataUpdateCoordinator[None]):
|
|||||||
|
|
||||||
if is_extended_multizone or is_legacy_multizone:
|
if is_extended_multizone or is_legacy_multizone:
|
||||||
self.active_effect = FirmwareEffect[self.device.effect.get("effect", "OFF")]
|
self.active_effect = FirmwareEffect[self.device.effect.get("effect", "OFF")]
|
||||||
if is_legacy_multizone and num_zones != len(device.color_zones):
|
if is_legacy_multizone and num_zones != self.get_number_of_zones():
|
||||||
# The number of zones has changed so we need
|
# The number of zones has changed so we need
|
||||||
# to update the zones again. This happens rarely.
|
# to update the zones again. This happens rarely.
|
||||||
await self.async_get_color_zones()
|
await self.async_get_color_zones()
|
||||||
|
@ -382,7 +382,7 @@ class LIFXMultiZone(LIFXColor):
|
|||||||
"""Send a color change to the bulb."""
|
"""Send a color change to the bulb."""
|
||||||
bulb = self.bulb
|
bulb = self.bulb
|
||||||
color_zones = bulb.color_zones
|
color_zones = bulb.color_zones
|
||||||
num_zones = len(color_zones)
|
num_zones = self.coordinator.get_number_of_zones()
|
||||||
|
|
||||||
# Zone brightness is not reported when powered off
|
# Zone brightness is not reported when powered off
|
||||||
if not self.is_on and hsbk[HSBK_BRIGHTNESS] is None:
|
if not self.is_on and hsbk[HSBK_BRIGHTNESS] is None:
|
||||||
|
@ -7,5 +7,5 @@
|
|||||||
"integration_type": "hub",
|
"integration_type": "hub",
|
||||||
"iot_class": "cloud_polling",
|
"iot_class": "cloud_polling",
|
||||||
"loggers": ["aionotion"],
|
"loggers": ["aionotion"],
|
||||||
"requirements": ["aionotion==2023.04.2"]
|
"requirements": ["aionotion==2023.05.0"]
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ from httpx import RequestError
|
|||||||
import onvif
|
import onvif
|
||||||
from onvif import ONVIFCamera
|
from onvif import ONVIFCamera
|
||||||
from onvif.exceptions import ONVIFError
|
from onvif.exceptions import ONVIFError
|
||||||
from zeep.exceptions import Fault, XMLParseError
|
from zeep.exceptions import Fault, TransportError, XMLParseError, XMLSyntaxError
|
||||||
|
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
@ -203,81 +203,104 @@ class ONVIFDevice:
|
|||||||
"""Warns if device and system date not synced."""
|
"""Warns if device and system date not synced."""
|
||||||
LOGGER.debug("%s: Setting up the ONVIF device management service", self.name)
|
LOGGER.debug("%s: Setting up the ONVIF device management service", self.name)
|
||||||
device_mgmt = self.device.create_devicemgmt_service()
|
device_mgmt = self.device.create_devicemgmt_service()
|
||||||
|
system_date = dt_util.utcnow()
|
||||||
|
|
||||||
LOGGER.debug("%s: Retrieving current device date/time", self.name)
|
LOGGER.debug("%s: Retrieving current device date/time", self.name)
|
||||||
try:
|
try:
|
||||||
system_date = dt_util.utcnow()
|
|
||||||
device_time = await device_mgmt.GetSystemDateAndTime()
|
device_time = await device_mgmt.GetSystemDateAndTime()
|
||||||
if not device_time:
|
|
||||||
LOGGER.debug(
|
|
||||||
"""Couldn't get device '%s' date/time.
|
|
||||||
GetSystemDateAndTime() return null/empty""",
|
|
||||||
self.name,
|
|
||||||
)
|
|
||||||
return
|
|
||||||
|
|
||||||
LOGGER.debug("%s: Device time: %s", self.name, device_time)
|
|
||||||
|
|
||||||
tzone = dt_util.DEFAULT_TIME_ZONE
|
|
||||||
cdate = device_time.LocalDateTime
|
|
||||||
if device_time.UTCDateTime:
|
|
||||||
tzone = dt_util.UTC
|
|
||||||
cdate = device_time.UTCDateTime
|
|
||||||
elif device_time.TimeZone:
|
|
||||||
tzone = dt_util.get_time_zone(device_time.TimeZone.TZ) or tzone
|
|
||||||
|
|
||||||
if cdate is None:
|
|
||||||
LOGGER.warning(
|
|
||||||
"%s: Could not retrieve date/time on this camera", self.name
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
cam_date = dt.datetime(
|
|
||||||
cdate.Date.Year,
|
|
||||||
cdate.Date.Month,
|
|
||||||
cdate.Date.Day,
|
|
||||||
cdate.Time.Hour,
|
|
||||||
cdate.Time.Minute,
|
|
||||||
cdate.Time.Second,
|
|
||||||
0,
|
|
||||||
tzone,
|
|
||||||
)
|
|
||||||
|
|
||||||
cam_date_utc = cam_date.astimezone(dt_util.UTC)
|
|
||||||
|
|
||||||
LOGGER.debug(
|
|
||||||
"%s: Device date/time: %s | System date/time: %s",
|
|
||||||
self.name,
|
|
||||||
cam_date_utc,
|
|
||||||
system_date,
|
|
||||||
)
|
|
||||||
|
|
||||||
dt_diff = cam_date - system_date
|
|
||||||
self._dt_diff_seconds = dt_diff.total_seconds()
|
|
||||||
|
|
||||||
# It could be off either direction, so we need to check the absolute value
|
|
||||||
if abs(self._dt_diff_seconds) > 5:
|
|
||||||
LOGGER.warning(
|
|
||||||
(
|
|
||||||
"The date/time on %s (UTC) is '%s', "
|
|
||||||
"which is different from the system '%s', "
|
|
||||||
"this could lead to authentication issues"
|
|
||||||
),
|
|
||||||
self.name,
|
|
||||||
cam_date_utc,
|
|
||||||
system_date,
|
|
||||||
)
|
|
||||||
if device_time.DateTimeType == "Manual":
|
|
||||||
# Set Date and Time ourselves if Date and Time is set manually in the camera.
|
|
||||||
await self.async_manually_set_date_and_time()
|
|
||||||
except RequestError as err:
|
except RequestError as err:
|
||||||
LOGGER.warning(
|
LOGGER.warning(
|
||||||
"Couldn't get device '%s' date/time. Error: %s", self.name, err
|
"Couldn't get device '%s' date/time. Error: %s", self.name, err
|
||||||
)
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
if not device_time:
|
||||||
|
LOGGER.debug(
|
||||||
|
"""Couldn't get device '%s' date/time.
|
||||||
|
GetSystemDateAndTime() return null/empty""",
|
||||||
|
self.name,
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
LOGGER.debug("%s: Device time: %s", self.name, device_time)
|
||||||
|
|
||||||
|
tzone = dt_util.DEFAULT_TIME_ZONE
|
||||||
|
cdate = device_time.LocalDateTime
|
||||||
|
if device_time.UTCDateTime:
|
||||||
|
tzone = dt_util.UTC
|
||||||
|
cdate = device_time.UTCDateTime
|
||||||
|
elif device_time.TimeZone:
|
||||||
|
tzone = dt_util.get_time_zone(device_time.TimeZone.TZ) or tzone
|
||||||
|
|
||||||
|
if cdate is None:
|
||||||
|
LOGGER.warning("%s: Could not retrieve date/time on this camera", self.name)
|
||||||
|
return
|
||||||
|
|
||||||
|
cam_date = dt.datetime(
|
||||||
|
cdate.Date.Year,
|
||||||
|
cdate.Date.Month,
|
||||||
|
cdate.Date.Day,
|
||||||
|
cdate.Time.Hour,
|
||||||
|
cdate.Time.Minute,
|
||||||
|
cdate.Time.Second,
|
||||||
|
0,
|
||||||
|
tzone,
|
||||||
|
)
|
||||||
|
|
||||||
|
cam_date_utc = cam_date.astimezone(dt_util.UTC)
|
||||||
|
|
||||||
|
LOGGER.debug(
|
||||||
|
"%s: Device date/time: %s | System date/time: %s",
|
||||||
|
self.name,
|
||||||
|
cam_date_utc,
|
||||||
|
system_date,
|
||||||
|
)
|
||||||
|
|
||||||
|
dt_diff = cam_date - system_date
|
||||||
|
self._dt_diff_seconds = dt_diff.total_seconds()
|
||||||
|
|
||||||
|
# It could be off either direction, so we need to check the absolute value
|
||||||
|
if abs(self._dt_diff_seconds) < 5:
|
||||||
|
return
|
||||||
|
|
||||||
|
LOGGER.warning(
|
||||||
|
(
|
||||||
|
"The date/time on %s (UTC) is '%s', "
|
||||||
|
"which is different from the system '%s', "
|
||||||
|
"this could lead to authentication issues"
|
||||||
|
),
|
||||||
|
self.name,
|
||||||
|
cam_date_utc,
|
||||||
|
system_date,
|
||||||
|
)
|
||||||
|
|
||||||
|
if device_time.DateTimeType != "Manual":
|
||||||
|
return
|
||||||
|
|
||||||
|
# Set Date and Time ourselves if Date and Time is set manually in the camera.
|
||||||
|
try:
|
||||||
|
await self.async_manually_set_date_and_time()
|
||||||
|
except (RequestError, TransportError):
|
||||||
|
LOGGER.warning("%s: Could not sync date/time on this camera", self.name)
|
||||||
|
|
||||||
async def async_get_device_info(self) -> DeviceInfo:
|
async def async_get_device_info(self) -> DeviceInfo:
|
||||||
"""Obtain information about this device."""
|
"""Obtain information about this device."""
|
||||||
device_mgmt = self.device.create_devicemgmt_service()
|
device_mgmt = self.device.create_devicemgmt_service()
|
||||||
device_info = await device_mgmt.GetDeviceInformation()
|
manufacturer = None
|
||||||
|
model = None
|
||||||
|
firmware_version = None
|
||||||
|
serial_number = None
|
||||||
|
try:
|
||||||
|
device_info = await device_mgmt.GetDeviceInformation()
|
||||||
|
except (XMLParseError, XMLSyntaxError, TransportError) as ex:
|
||||||
|
# Some cameras have invalid UTF-8 in their device information (TransportError)
|
||||||
|
# and others have completely invalid XML (XMLParseError, XMLSyntaxError)
|
||||||
|
LOGGER.warning("%s: Failed to fetch device information: %s", self.name, ex)
|
||||||
|
else:
|
||||||
|
manufacturer = device_info.Manufacturer
|
||||||
|
model = device_info.Model
|
||||||
|
firmware_version = device_info.FirmwareVersion
|
||||||
|
serial_number = device_info.SerialNumber
|
||||||
|
|
||||||
# Grab the last MAC address for backwards compatibility
|
# Grab the last MAC address for backwards compatibility
|
||||||
mac = None
|
mac = None
|
||||||
@ -297,10 +320,10 @@ class ONVIFDevice:
|
|||||||
)
|
)
|
||||||
|
|
||||||
return DeviceInfo(
|
return DeviceInfo(
|
||||||
device_info.Manufacturer,
|
manufacturer,
|
||||||
device_info.Model,
|
model,
|
||||||
device_info.FirmwareVersion,
|
firmware_version,
|
||||||
device_info.SerialNumber,
|
serial_number,
|
||||||
mac,
|
mac,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -328,7 +351,7 @@ class ONVIFDevice:
|
|||||||
"""Start the event handler."""
|
"""Start the event handler."""
|
||||||
with suppress(*GET_CAPABILITIES_EXCEPTIONS, XMLParseError):
|
with suppress(*GET_CAPABILITIES_EXCEPTIONS, XMLParseError):
|
||||||
onvif_capabilities = self.onvif_capabilities or {}
|
onvif_capabilities = self.onvif_capabilities or {}
|
||||||
pull_point_support = onvif_capabilities.get("Events", {}).get(
|
pull_point_support = (onvif_capabilities.get("Events") or {}).get(
|
||||||
"WSPullPointSupport"
|
"WSPullPointSupport"
|
||||||
)
|
)
|
||||||
LOGGER.debug("%s: WSPullPointSupport: %s", self.name, pull_point_support)
|
LOGGER.debug("%s: WSPullPointSupport: %s", self.name, pull_point_support)
|
||||||
|
@ -8,7 +8,7 @@ from .backports.enum import StrEnum
|
|||||||
APPLICATION_NAME: Final = "HomeAssistant"
|
APPLICATION_NAME: Final = "HomeAssistant"
|
||||||
MAJOR_VERSION: Final = 2023
|
MAJOR_VERSION: Final = 2023
|
||||||
MINOR_VERSION: Final = 5
|
MINOR_VERSION: Final = 5
|
||||||
PATCH_VERSION: Final = "0"
|
PATCH_VERSION: Final = "1"
|
||||||
__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, 10, 0)
|
REQUIRED_PYTHON_VER: Final[tuple[int, int, int]] = (3, 10, 0)
|
||||||
|
@ -14,7 +14,7 @@ bcrypt==4.0.1
|
|||||||
bleak-retry-connector==3.0.2
|
bleak-retry-connector==3.0.2
|
||||||
bleak==0.20.2
|
bleak==0.20.2
|
||||||
bluetooth-adapters==0.15.3
|
bluetooth-adapters==0.15.3
|
||||||
bluetooth-auto-recovery==1.1.1
|
bluetooth-auto-recovery==1.1.2
|
||||||
bluetooth-data-tools==0.4.0
|
bluetooth-data-tools==0.4.0
|
||||||
certifi>=2021.5.30
|
certifi>=2021.5.30
|
||||||
ciso8601==2.3.0
|
ciso8601==2.3.0
|
||||||
@ -25,7 +25,7 @@ ha-av==10.0.0
|
|||||||
hass-nabucasa==0.66.2
|
hass-nabucasa==0.66.2
|
||||||
hassil==1.0.6
|
hassil==1.0.6
|
||||||
home-assistant-bluetooth==1.10.0
|
home-assistant-bluetooth==1.10.0
|
||||||
home-assistant-frontend==20230503.1
|
home-assistant-frontend==20230503.2
|
||||||
home-assistant-intents==2023.4.26
|
home-assistant-intents==2023.4.26
|
||||||
httpx==0.24.0
|
httpx==0.24.0
|
||||||
ifaddr==0.1.7
|
ifaddr==0.1.7
|
||||||
|
@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "homeassistant"
|
name = "homeassistant"
|
||||||
version = "2023.5.0"
|
version = "2023.5.1"
|
||||||
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"
|
||||||
|
@ -223,7 +223,7 @@ aionanoleaf==0.2.1
|
|||||||
aionotify==0.2.0
|
aionotify==0.2.0
|
||||||
|
|
||||||
# homeassistant.components.notion
|
# homeassistant.components.notion
|
||||||
aionotion==2023.04.2
|
aionotion==2023.05.0
|
||||||
|
|
||||||
# homeassistant.components.oncue
|
# homeassistant.components.oncue
|
||||||
aiooncue==0.3.4
|
aiooncue==0.3.4
|
||||||
@ -465,7 +465,7 @@ bluemaestro-ble==0.2.3
|
|||||||
bluetooth-adapters==0.15.3
|
bluetooth-adapters==0.15.3
|
||||||
|
|
||||||
# homeassistant.components.bluetooth
|
# homeassistant.components.bluetooth
|
||||||
bluetooth-auto-recovery==1.1.1
|
bluetooth-auto-recovery==1.1.2
|
||||||
|
|
||||||
# homeassistant.components.bluetooth
|
# homeassistant.components.bluetooth
|
||||||
# homeassistant.components.esphome
|
# homeassistant.components.esphome
|
||||||
@ -911,7 +911,7 @@ hole==0.8.0
|
|||||||
holidays==0.21.13
|
holidays==0.21.13
|
||||||
|
|
||||||
# homeassistant.components.frontend
|
# homeassistant.components.frontend
|
||||||
home-assistant-frontend==20230503.1
|
home-assistant-frontend==20230503.2
|
||||||
|
|
||||||
# homeassistant.components.conversation
|
# homeassistant.components.conversation
|
||||||
home-assistant-intents==2023.4.26
|
home-assistant-intents==2023.4.26
|
||||||
|
@ -204,7 +204,7 @@ aiomusiccast==0.14.8
|
|||||||
aionanoleaf==0.2.1
|
aionanoleaf==0.2.1
|
||||||
|
|
||||||
# homeassistant.components.notion
|
# homeassistant.components.notion
|
||||||
aionotion==2023.04.2
|
aionotion==2023.05.0
|
||||||
|
|
||||||
# homeassistant.components.oncue
|
# homeassistant.components.oncue
|
||||||
aiooncue==0.3.4
|
aiooncue==0.3.4
|
||||||
@ -385,7 +385,7 @@ bluemaestro-ble==0.2.3
|
|||||||
bluetooth-adapters==0.15.3
|
bluetooth-adapters==0.15.3
|
||||||
|
|
||||||
# homeassistant.components.bluetooth
|
# homeassistant.components.bluetooth
|
||||||
bluetooth-auto-recovery==1.1.1
|
bluetooth-auto-recovery==1.1.2
|
||||||
|
|
||||||
# homeassistant.components.bluetooth
|
# homeassistant.components.bluetooth
|
||||||
# homeassistant.components.esphome
|
# homeassistant.components.esphome
|
||||||
@ -700,7 +700,7 @@ hole==0.8.0
|
|||||||
holidays==0.21.13
|
holidays==0.21.13
|
||||||
|
|
||||||
# homeassistant.components.frontend
|
# homeassistant.components.frontend
|
||||||
home-assistant-frontend==20230503.1
|
home-assistant-frontend==20230503.2
|
||||||
|
|
||||||
# homeassistant.components.conversation
|
# homeassistant.components.conversation
|
||||||
home-assistant-intents==2023.4.26
|
home-assistant-intents==2023.4.26
|
||||||
|
@ -628,7 +628,7 @@ async def test_alexa_config_migrate_expose_entity_prefs(
|
|||||||
"cloud.alexa": {"should_expose": True}
|
"cloud.alexa": {"should_expose": True}
|
||||||
}
|
}
|
||||||
assert async_get_entity_settings(hass, entity_migrated.entity_id) == {
|
assert async_get_entity_settings(hass, entity_migrated.entity_id) == {
|
||||||
"cloud.alexa": {"should_expose": False}
|
"cloud.alexa": {"should_expose": True}
|
||||||
}
|
}
|
||||||
assert async_get_entity_settings(hass, entity_config.entity_id) == {
|
assert async_get_entity_settings(hass, entity_config.entity_id) == {
|
||||||
"cloud.alexa": {"should_expose": False}
|
"cloud.alexa": {"should_expose": False}
|
||||||
|
@ -580,7 +580,7 @@ async def test_google_config_migrate_expose_entity_prefs(
|
|||||||
"cloud.google_assistant": {"should_expose": True}
|
"cloud.google_assistant": {"should_expose": True}
|
||||||
}
|
}
|
||||||
assert async_get_entity_settings(hass, entity_migrated.entity_id) == {
|
assert async_get_entity_settings(hass, entity_migrated.entity_id) == {
|
||||||
"cloud.google_assistant": {"should_expose": False}
|
"cloud.google_assistant": {"should_expose": True}
|
||||||
}
|
}
|
||||||
assert async_get_entity_settings(hass, entity_no_2fa_exposed.entity_id) == {
|
assert async_get_entity_settings(hass, entity_no_2fa_exposed.entity_id) == {
|
||||||
"cloud.google_assistant": {"disable_2fa": True, "should_expose": True}
|
"cloud.google_assistant": {"disable_2fa": True, "should_expose": True}
|
||||||
|
@ -36,6 +36,7 @@ from homeassistant.components.light import (
|
|||||||
ATTR_TRANSITION,
|
ATTR_TRANSITION,
|
||||||
ATTR_XY_COLOR,
|
ATTR_XY_COLOR,
|
||||||
DOMAIN as LIGHT_DOMAIN,
|
DOMAIN as LIGHT_DOMAIN,
|
||||||
|
SERVICE_TURN_ON,
|
||||||
ColorMode,
|
ColorMode,
|
||||||
)
|
)
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
@ -1741,3 +1742,46 @@ async def test_set_hev_cycle_state_fails_for_color_bulb(hass: HomeAssistant) ->
|
|||||||
{ATTR_ENTITY_ID: entity_id, ATTR_POWER: True},
|
{ATTR_ENTITY_ID: entity_id, ATTR_POWER: True},
|
||||||
blocking=True,
|
blocking=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def test_light_strip_zones_not_populated_yet(hass: HomeAssistant) -> None:
|
||||||
|
"""Test a light strip were zones are not populated initially."""
|
||||||
|
already_migrated_config_entry = MockConfigEntry(
|
||||||
|
domain=DOMAIN, data={CONF_HOST: "127.0.0.1"}, unique_id=SERIAL
|
||||||
|
)
|
||||||
|
already_migrated_config_entry.add_to_hass(hass)
|
||||||
|
bulb = _mocked_light_strip()
|
||||||
|
bulb.power_level = 65535
|
||||||
|
bulb.color_zones = None
|
||||||
|
bulb.color = [65535, 65535, 65535, 65535]
|
||||||
|
with _patch_discovery(device=bulb), _patch_config_flow_try_connect(
|
||||||
|
device=bulb
|
||||||
|
), _patch_device(device=bulb):
|
||||||
|
await async_setup_component(hass, lifx.DOMAIN, {lifx.DOMAIN: {}})
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
entity_id = "light.my_bulb"
|
||||||
|
|
||||||
|
state = hass.states.get(entity_id)
|
||||||
|
assert state.state == "on"
|
||||||
|
attributes = state.attributes
|
||||||
|
assert attributes[ATTR_BRIGHTNESS] == 255
|
||||||
|
assert attributes[ATTR_COLOR_MODE] == ColorMode.HS
|
||||||
|
assert attributes[ATTR_SUPPORTED_COLOR_MODES] == [
|
||||||
|
ColorMode.COLOR_TEMP,
|
||||||
|
ColorMode.HS,
|
||||||
|
]
|
||||||
|
assert attributes[ATTR_HS_COLOR] == (360.0, 100.0)
|
||||||
|
assert attributes[ATTR_RGB_COLOR] == (255, 0, 0)
|
||||||
|
assert attributes[ATTR_XY_COLOR] == (0.701, 0.299)
|
||||||
|
|
||||||
|
await hass.services.async_call(
|
||||||
|
LIGHT_DOMAIN, SERVICE_TURN_ON, {ATTR_ENTITY_ID: entity_id}, blocking=True
|
||||||
|
)
|
||||||
|
assert bulb.set_power.calls[0][0][0] is True
|
||||||
|
bulb.set_power.reset_mock()
|
||||||
|
|
||||||
|
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=30))
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
state = hass.states.get(entity_id)
|
||||||
|
assert state.state == STATE_ON
|
||||||
|
Loading…
x
Reference in New Issue
Block a user