mirror of
https://github.com/home-assistant/core.git
synced 2025-07-28 23:57:06 +00:00
Merge pull request #54117 from home-assistant/rc
This commit is contained in:
commit
a07048aacf
@ -71,9 +71,6 @@ from homeassistant.loader import bind_hass
|
|||||||
from homeassistant.util.dt import parse_datetime
|
from homeassistant.util.dt import parse_datetime
|
||||||
|
|
||||||
from .config import AutomationConfig, async_validate_config_item
|
from .config import AutomationConfig, async_validate_config_item
|
||||||
|
|
||||||
# Not used except by packages to check config structure
|
|
||||||
from .config import PLATFORM_SCHEMA # noqa: F401
|
|
||||||
from .const import (
|
from .const import (
|
||||||
CONF_ACTION,
|
CONF_ACTION,
|
||||||
CONF_INITIAL_STATE,
|
CONF_INITIAL_STATE,
|
||||||
|
@ -37,6 +37,8 @@ from .helpers import async_get_blueprints
|
|||||||
# mypy: allow-untyped-calls, allow-untyped-defs
|
# mypy: allow-untyped-calls, allow-untyped-defs
|
||||||
# mypy: no-check-untyped-defs, no-warn-return-any
|
# mypy: no-check-untyped-defs, no-warn-return-any
|
||||||
|
|
||||||
|
PACKAGE_MERGE_HINT = "list"
|
||||||
|
|
||||||
_CONDITION_SCHEMA = vol.All(cv.ensure_list, [cv.CONDITION_SCHEMA])
|
_CONDITION_SCHEMA = vol.All(cv.ensure_list, [cv.CONDITION_SCHEMA])
|
||||||
|
|
||||||
PLATFORM_SCHEMA = vol.All(
|
PLATFORM_SCHEMA = vol.All(
|
||||||
|
@ -81,12 +81,12 @@ def _retrieve_max_kb_s_received_state(status: FritzStatus, last_value: str) -> f
|
|||||||
|
|
||||||
def _retrieve_gb_sent_state(status: FritzStatus, last_value: str) -> float:
|
def _retrieve_gb_sent_state(status: FritzStatus, last_value: str) -> float:
|
||||||
"""Return upload total data."""
|
"""Return upload total data."""
|
||||||
return round(status.bytes_sent * 8 / 1000 / 1000 / 1000, 1) # type: ignore[no-any-return]
|
return round(status.bytes_sent / 1000 / 1000 / 1000, 1) # type: ignore[no-any-return]
|
||||||
|
|
||||||
|
|
||||||
def _retrieve_gb_received_state(status: FritzStatus, last_value: str) -> float:
|
def _retrieve_gb_received_state(status: FritzStatus, last_value: str) -> float:
|
||||||
"""Return download total data."""
|
"""Return download total data."""
|
||||||
return round(status.bytes_received * 8 / 1000 / 1000 / 1000, 1) # type: ignore[no-any-return]
|
return round(status.bytes_received / 1000 / 1000 / 1000, 1) # type: ignore[no-any-return]
|
||||||
|
|
||||||
|
|
||||||
class SensorData(TypedDict, total=False):
|
class SensorData(TypedDict, total=False):
|
||||||
|
@ -13,7 +13,6 @@ from fritzconnection.core.exceptions import (
|
|||||||
FritzSecurityError,
|
FritzSecurityError,
|
||||||
FritzServiceError,
|
FritzServiceError,
|
||||||
)
|
)
|
||||||
import slugify as unicode_slug
|
|
||||||
import xmltodict
|
import xmltodict
|
||||||
|
|
||||||
from homeassistant.components.network import async_get_source_ip
|
from homeassistant.components.network import async_get_source_ip
|
||||||
@ -248,10 +247,18 @@ def wifi_entities_list(
|
|||||||
)
|
)
|
||||||
if network_info:
|
if network_info:
|
||||||
ssid = network_info["NewSSID"]
|
ssid = network_info["NewSSID"]
|
||||||
if unicode_slug.slugify(ssid, lowercase=False) in networks.values():
|
_LOGGER.debug("SSID from device: <%s>", ssid)
|
||||||
|
if (
|
||||||
|
slugify(
|
||||||
|
ssid,
|
||||||
|
)
|
||||||
|
in [slugify(v) for v in networks.values()]
|
||||||
|
):
|
||||||
|
_LOGGER.debug("SSID duplicated, adding suffix")
|
||||||
networks[i] = f'{ssid} {std_table[network_info["NewStandard"]]}'
|
networks[i] = f'{ssid} {std_table[network_info["NewStandard"]]}'
|
||||||
else:
|
else:
|
||||||
networks[i] = ssid
|
networks[i] = ssid
|
||||||
|
_LOGGER.debug("SSID normalized: <%s>", networks[i])
|
||||||
|
|
||||||
return [
|
return [
|
||||||
FritzBoxWifiSwitch(fritzbox_tools, device_friendly_name, net, network_name)
|
FritzBoxWifiSwitch(fritzbox_tools, device_friendly_name, net, network_name)
|
||||||
|
@ -228,17 +228,17 @@ class HomeAccessory(Accessory):
|
|||||||
self.config = config or {}
|
self.config = config or {}
|
||||||
domain = split_entity_id(entity_id)[0].replace("_", " ")
|
domain = split_entity_id(entity_id)[0].replace("_", " ")
|
||||||
|
|
||||||
if ATTR_MANUFACTURER in self.config:
|
if self.config.get(ATTR_MANUFACTURER) is not None:
|
||||||
manufacturer = self.config[ATTR_MANUFACTURER]
|
manufacturer = self.config[ATTR_MANUFACTURER]
|
||||||
elif ATTR_INTEGRATION in self.config:
|
elif self.config.get(ATTR_INTEGRATION) is not None:
|
||||||
manufacturer = self.config[ATTR_INTEGRATION].replace("_", " ").title()
|
manufacturer = self.config[ATTR_INTEGRATION].replace("_", " ").title()
|
||||||
else:
|
else:
|
||||||
manufacturer = f"{MANUFACTURER} {domain}".title()
|
manufacturer = f"{MANUFACTURER} {domain}".title()
|
||||||
if ATTR_MODEL in self.config:
|
if self.config.get(ATTR_MODEL) is not None:
|
||||||
model = self.config[ATTR_MODEL]
|
model = self.config[ATTR_MODEL]
|
||||||
else:
|
else:
|
||||||
model = domain.title()
|
model = domain.title()
|
||||||
if ATTR_SOFTWARE_VERSION in self.config:
|
if self.config.get(ATTR_SOFTWARE_VERSION) is not None:
|
||||||
sw_version = format_sw_version(self.config[ATTR_SOFTWARE_VERSION])
|
sw_version = format_sw_version(self.config[ATTR_SOFTWARE_VERSION])
|
||||||
else:
|
else:
|
||||||
sw_version = __version__
|
sw_version = __version__
|
||||||
|
@ -57,6 +57,8 @@ VALVE_TYPE = {
|
|||||||
|
|
||||||
ACTIVATE_ONLY_SWITCH_DOMAINS = {"scene", "script"}
|
ACTIVATE_ONLY_SWITCH_DOMAINS = {"scene", "script"}
|
||||||
|
|
||||||
|
ACTIVATE_ONLY_RESET_SECONDS = 10
|
||||||
|
|
||||||
|
|
||||||
@TYPES.register("Outlet")
|
@TYPES.register("Outlet")
|
||||||
class Outlet(HomeAccessory):
|
class Outlet(HomeAccessory):
|
||||||
@ -141,7 +143,7 @@ class Switch(HomeAccessory):
|
|||||||
self.async_call_service(self._domain, service, params)
|
self.async_call_service(self._domain, service, params)
|
||||||
|
|
||||||
if self.activate_only:
|
if self.activate_only:
|
||||||
async_call_later(self.hass, 1, self.reset_switch)
|
async_call_later(self.hass, ACTIVATE_ONLY_RESET_SECONDS, self.reset_switch)
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def async_update_state(self, new_state):
|
def async_update_state(self, new_state):
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"name": "Litter-Robot",
|
"name": "Litter-Robot",
|
||||||
"config_flow": true,
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/integrations/litterrobot",
|
"documentation": "https://www.home-assistant.io/integrations/litterrobot",
|
||||||
"requirements": ["pylitterbot==2021.7.2"],
|
"requirements": ["pylitterbot==2021.8.0"],
|
||||||
"codeowners": ["@natekspencer"],
|
"codeowners": ["@natekspencer"],
|
||||||
"iot_class": "cloud_polling"
|
"iot_class": "cloud_polling"
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ from homeassistant.const import (
|
|||||||
CONF_PASSWORD,
|
CONF_PASSWORD,
|
||||||
CONF_TYPE,
|
CONF_TYPE,
|
||||||
CONF_USERNAME,
|
CONF_USERNAME,
|
||||||
|
DEVICE_CLASS_ENERGY,
|
||||||
DEVICE_CLASS_POWER,
|
DEVICE_CLASS_POWER,
|
||||||
DEVICE_CLASS_TEMPERATURE,
|
DEVICE_CLASS_TEMPERATURE,
|
||||||
ENERGY_KILO_WATT_HOUR,
|
ENERGY_KILO_WATT_HOUR,
|
||||||
@ -204,6 +205,8 @@ class SAJsensor(SensorEntity):
|
|||||||
"""Return the device class the sensor belongs to."""
|
"""Return the device class the sensor belongs to."""
|
||||||
if self.unit_of_measurement == POWER_WATT:
|
if self.unit_of_measurement == POWER_WATT:
|
||||||
return DEVICE_CLASS_POWER
|
return DEVICE_CLASS_POWER
|
||||||
|
if self.unit_of_measurement == ENERGY_KILO_WATT_HOUR:
|
||||||
|
return DEVICE_CLASS_ENERGY
|
||||||
if (
|
if (
|
||||||
self.unit_of_measurement == TEMP_CELSIUS
|
self.unit_of_measurement == TEMP_CELSIUS
|
||||||
or self._sensor.unit == TEMP_FAHRENHEIT
|
or self._sensor.unit == TEMP_FAHRENHEIT
|
||||||
|
@ -39,6 +39,8 @@ from .const import (
|
|||||||
)
|
)
|
||||||
from .helpers import async_get_blueprints
|
from .helpers import async_get_blueprints
|
||||||
|
|
||||||
|
PACKAGE_MERGE_HINT = "dict"
|
||||||
|
|
||||||
SCRIPT_ENTITY_SCHEMA = make_script_schema(
|
SCRIPT_ENTITY_SCHEMA = make_script_schema(
|
||||||
{
|
{
|
||||||
vol.Optional(CONF_ALIAS): cv.string,
|
vol.Optional(CONF_ALIAS): cv.string,
|
||||||
|
@ -285,7 +285,6 @@ class ShellyBlockAttributeEntity(ShellyBlockEntity, entity.Entity):
|
|||||||
self._unit: None | str | Callable[[dict], str] = unit
|
self._unit: None | str | Callable[[dict], str] = unit
|
||||||
self._unique_id: str = f"{super().unique_id}-{self.attribute}"
|
self._unique_id: str = f"{super().unique_id}-{self.attribute}"
|
||||||
self._name = get_entity_name(wrapper.device, block, self.description.name)
|
self._name = get_entity_name(wrapper.device, block, self.description.name)
|
||||||
self._last_value: str | None = None
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def unique_id(self) -> str:
|
def unique_id(self) -> str:
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
"""Sensor for Shelly."""
|
"""Sensor for Shelly."""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from datetime import datetime
|
from datetime import timedelta
|
||||||
|
import logging
|
||||||
from typing import Final, cast
|
from typing import Final, cast
|
||||||
|
|
||||||
|
import aioshelly
|
||||||
|
|
||||||
from homeassistant.components import sensor
|
from homeassistant.components import sensor
|
||||||
from homeassistant.components.sensor import SensorEntity
|
from homeassistant.components.sensor import SensorEntity
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
@ -23,6 +26,7 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
|||||||
from homeassistant.helpers.typing import StateType
|
from homeassistant.helpers.typing import StateType
|
||||||
from homeassistant.util import dt
|
from homeassistant.util import dt
|
||||||
|
|
||||||
|
from . import ShellyDeviceWrapper
|
||||||
from .const import LAST_RESET_NEVER, LAST_RESET_UPTIME, SHAIR_MAX_WORK_HOURS
|
from .const import LAST_RESET_NEVER, LAST_RESET_UPTIME, SHAIR_MAX_WORK_HOURS
|
||||||
from .entity import (
|
from .entity import (
|
||||||
BlockAttributeDescription,
|
BlockAttributeDescription,
|
||||||
@ -35,6 +39,8 @@ from .entity import (
|
|||||||
)
|
)
|
||||||
from .utils import get_device_uptime, temperature_unit
|
from .utils import get_device_uptime, temperature_unit
|
||||||
|
|
||||||
|
_LOGGER: Final = logging.getLogger(__name__)
|
||||||
|
|
||||||
SENSORS: Final = {
|
SENSORS: Final = {
|
||||||
("device", "battery"): BlockAttributeDescription(
|
("device", "battery"): BlockAttributeDescription(
|
||||||
name="Battery",
|
name="Battery",
|
||||||
@ -255,9 +261,39 @@ async def async_setup_entry(
|
|||||||
class ShellySensor(ShellyBlockAttributeEntity, SensorEntity):
|
class ShellySensor(ShellyBlockAttributeEntity, SensorEntity):
|
||||||
"""Represent a shelly sensor."""
|
"""Represent a shelly sensor."""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
wrapper: ShellyDeviceWrapper,
|
||||||
|
block: aioshelly.Block,
|
||||||
|
attribute: str,
|
||||||
|
description: BlockAttributeDescription,
|
||||||
|
) -> None:
|
||||||
|
"""Initialize sensor."""
|
||||||
|
super().__init__(wrapper, block, attribute, description)
|
||||||
|
self._last_value: float | None = None
|
||||||
|
|
||||||
|
if description.last_reset == LAST_RESET_NEVER:
|
||||||
|
self._attr_last_reset = dt.utc_from_timestamp(0)
|
||||||
|
elif description.last_reset == LAST_RESET_UPTIME:
|
||||||
|
self._attr_last_reset = (
|
||||||
|
dt.utcnow() - timedelta(seconds=wrapper.device.status["uptime"])
|
||||||
|
).replace(second=0, microsecond=0)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def state(self) -> StateType:
|
def state(self) -> StateType:
|
||||||
"""Return value of sensor."""
|
"""Return value of sensor."""
|
||||||
|
if (
|
||||||
|
self.description.last_reset == LAST_RESET_UPTIME
|
||||||
|
and self.attribute_value is not None
|
||||||
|
):
|
||||||
|
value = cast(float, self.attribute_value)
|
||||||
|
|
||||||
|
if self._last_value and self._last_value > value:
|
||||||
|
self._attr_last_reset = dt.utcnow().replace(second=0, microsecond=0)
|
||||||
|
_LOGGER.info("Energy reset detected for entity %s", self.name)
|
||||||
|
|
||||||
|
self._last_value = value
|
||||||
|
|
||||||
return self.attribute_value
|
return self.attribute_value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -265,20 +301,6 @@ class ShellySensor(ShellyBlockAttributeEntity, SensorEntity):
|
|||||||
"""State class of sensor."""
|
"""State class of sensor."""
|
||||||
return self.description.state_class
|
return self.description.state_class
|
||||||
|
|
||||||
@property
|
|
||||||
def last_reset(self) -> datetime | None:
|
|
||||||
"""State class of sensor."""
|
|
||||||
if self.description.last_reset == LAST_RESET_UPTIME:
|
|
||||||
self._last_value = get_device_uptime(
|
|
||||||
self.wrapper.device.status, self._last_value
|
|
||||||
)
|
|
||||||
return dt.parse_datetime(self._last_value)
|
|
||||||
|
|
||||||
if self.description.last_reset == LAST_RESET_NEVER:
|
|
||||||
return dt.utc_from_timestamp(0)
|
|
||||||
|
|
||||||
return None
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def unit_of_measurement(self) -> str | None:
|
def unit_of_measurement(self) -> str | None:
|
||||||
"""Return unit of sensor."""
|
"""Return unit of sensor."""
|
||||||
|
@ -13,6 +13,8 @@ from homeassistant.helpers.trigger import async_validate_trigger_config
|
|||||||
from . import binary_sensor as binary_sensor_platform, sensor as sensor_platform
|
from . import binary_sensor as binary_sensor_platform, sensor as sensor_platform
|
||||||
from .const import CONF_TRIGGER, DOMAIN
|
from .const import CONF_TRIGGER, DOMAIN
|
||||||
|
|
||||||
|
PACKAGE_MERGE_HINT = "list"
|
||||||
|
|
||||||
CONFIG_SECTION_SCHEMA = vol.Schema(
|
CONFIG_SECTION_SCHEMA = vol.Schema(
|
||||||
{
|
{
|
||||||
vol.Optional(CONF_UNIQUE_ID): cv.string,
|
vol.Optional(CONF_UNIQUE_ID): cv.string,
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
"domain": "zeroconf",
|
"domain": "zeroconf",
|
||||||
"name": "Zero-configuration networking (zeroconf)",
|
"name": "Zero-configuration networking (zeroconf)",
|
||||||
"documentation": "https://www.home-assistant.io/integrations/zeroconf",
|
"documentation": "https://www.home-assistant.io/integrations/zeroconf",
|
||||||
"requirements": ["zeroconf==0.33.2"],
|
"requirements": ["zeroconf==0.33.3"],
|
||||||
"dependencies": ["network", "api"],
|
"dependencies": ["network", "api"],
|
||||||
"codeowners": ["@bdraco"],
|
"codeowners": ["@bdraco"],
|
||||||
"quality_scale": "internal",
|
"quality_scale": "internal",
|
||||||
|
@ -9,11 +9,11 @@
|
|||||||
"pyserial-asyncio==0.5",
|
"pyserial-asyncio==0.5",
|
||||||
"zha-quirks==0.0.59",
|
"zha-quirks==0.0.59",
|
||||||
"zigpy-cc==0.5.2",
|
"zigpy-cc==0.5.2",
|
||||||
"zigpy-deconz==0.12.0",
|
"zigpy-deconz==0.12.1",
|
||||||
"zigpy==0.36.1",
|
"zigpy==0.36.1",
|
||||||
"zigpy-xbee==0.13.0",
|
"zigpy-xbee==0.13.0",
|
||||||
"zigpy-zigate==0.7.3",
|
"zigpy-zigate==0.7.3",
|
||||||
"zigpy-znp==0.5.2"
|
"zigpy-znp==0.5.3"
|
||||||
],
|
],
|
||||||
"codeowners": ["@dmulcahey", "@adminiuga"],
|
"codeowners": ["@dmulcahey", "@adminiuga"],
|
||||||
"zeroconf": [
|
"zeroconf": [
|
||||||
|
@ -723,7 +723,22 @@ async def merge_packages_config(
|
|||||||
_log_pkg_error(pack_name, comp_name, config, str(ex))
|
_log_pkg_error(pack_name, comp_name, config, str(ex))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
merge_list = hasattr(component, "PLATFORM_SCHEMA")
|
try:
|
||||||
|
config_platform: ModuleType | None = integration.get_platform("config")
|
||||||
|
# Test if config platform has a config validator
|
||||||
|
if not hasattr(config_platform, "async_validate_config"):
|
||||||
|
config_platform = None
|
||||||
|
except ImportError:
|
||||||
|
config_platform = None
|
||||||
|
|
||||||
|
merge_list = False
|
||||||
|
|
||||||
|
# If integration has a custom config validator, it needs to provide a hint.
|
||||||
|
if config_platform is not None:
|
||||||
|
merge_list = config_platform.PACKAGE_MERGE_HINT == "list" # type: ignore[attr-defined]
|
||||||
|
|
||||||
|
if not merge_list:
|
||||||
|
merge_list = hasattr(component, "PLATFORM_SCHEMA")
|
||||||
|
|
||||||
if not merge_list and hasattr(component, "CONFIG_SCHEMA"):
|
if not merge_list and hasattr(component, "CONFIG_SCHEMA"):
|
||||||
merge_list = _identify_config_schema(component) == "list"
|
merge_list = _identify_config_schema(component) == "list"
|
||||||
|
@ -5,7 +5,7 @@ from typing import Final
|
|||||||
|
|
||||||
MAJOR_VERSION: Final = 2021
|
MAJOR_VERSION: Final = 2021
|
||||||
MINOR_VERSION: Final = 8
|
MINOR_VERSION: Final = 8
|
||||||
PATCH_VERSION: Final = "1"
|
PATCH_VERSION: Final = "2"
|
||||||
__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)
|
||||||
|
@ -33,7 +33,7 @@ sqlalchemy==1.4.17
|
|||||||
voluptuous-serialize==2.4.0
|
voluptuous-serialize==2.4.0
|
||||||
voluptuous==0.12.1
|
voluptuous==0.12.1
|
||||||
yarl==1.6.3
|
yarl==1.6.3
|
||||||
zeroconf==0.33.2
|
zeroconf==0.33.3
|
||||||
|
|
||||||
pycryptodome>=3.6.6
|
pycryptodome>=3.6.6
|
||||||
|
|
||||||
|
@ -1562,7 +1562,7 @@ pylibrespot-java==0.1.0
|
|||||||
pylitejet==0.3.0
|
pylitejet==0.3.0
|
||||||
|
|
||||||
# homeassistant.components.litterrobot
|
# homeassistant.components.litterrobot
|
||||||
pylitterbot==2021.7.2
|
pylitterbot==2021.8.0
|
||||||
|
|
||||||
# homeassistant.components.loopenergy
|
# homeassistant.components.loopenergy
|
||||||
pyloopenergy==0.2.1
|
pyloopenergy==0.2.1
|
||||||
@ -2439,7 +2439,7 @@ zeep[async]==4.0.0
|
|||||||
zengge==0.2
|
zengge==0.2
|
||||||
|
|
||||||
# homeassistant.components.zeroconf
|
# homeassistant.components.zeroconf
|
||||||
zeroconf==0.33.2
|
zeroconf==0.33.3
|
||||||
|
|
||||||
# homeassistant.components.zha
|
# homeassistant.components.zha
|
||||||
zha-quirks==0.0.59
|
zha-quirks==0.0.59
|
||||||
@ -2454,7 +2454,7 @@ ziggo-mediabox-xl==1.1.0
|
|||||||
zigpy-cc==0.5.2
|
zigpy-cc==0.5.2
|
||||||
|
|
||||||
# homeassistant.components.zha
|
# homeassistant.components.zha
|
||||||
zigpy-deconz==0.12.0
|
zigpy-deconz==0.12.1
|
||||||
|
|
||||||
# homeassistant.components.zha
|
# homeassistant.components.zha
|
||||||
zigpy-xbee==0.13.0
|
zigpy-xbee==0.13.0
|
||||||
@ -2463,7 +2463,7 @@ zigpy-xbee==0.13.0
|
|||||||
zigpy-zigate==0.7.3
|
zigpy-zigate==0.7.3
|
||||||
|
|
||||||
# homeassistant.components.zha
|
# homeassistant.components.zha
|
||||||
zigpy-znp==0.5.2
|
zigpy-znp==0.5.3
|
||||||
|
|
||||||
# homeassistant.components.zha
|
# homeassistant.components.zha
|
||||||
zigpy==0.36.1
|
zigpy==0.36.1
|
||||||
|
@ -884,7 +884,7 @@ pylibrespot-java==0.1.0
|
|||||||
pylitejet==0.3.0
|
pylitejet==0.3.0
|
||||||
|
|
||||||
# homeassistant.components.litterrobot
|
# homeassistant.components.litterrobot
|
||||||
pylitterbot==2021.7.2
|
pylitterbot==2021.8.0
|
||||||
|
|
||||||
# homeassistant.components.lutron_caseta
|
# homeassistant.components.lutron_caseta
|
||||||
pylutron-caseta==0.11.0
|
pylutron-caseta==0.11.0
|
||||||
@ -1341,7 +1341,7 @@ youless-api==0.10
|
|||||||
zeep[async]==4.0.0
|
zeep[async]==4.0.0
|
||||||
|
|
||||||
# homeassistant.components.zeroconf
|
# homeassistant.components.zeroconf
|
||||||
zeroconf==0.33.2
|
zeroconf==0.33.3
|
||||||
|
|
||||||
# homeassistant.components.zha
|
# homeassistant.components.zha
|
||||||
zha-quirks==0.0.59
|
zha-quirks==0.0.59
|
||||||
@ -1350,7 +1350,7 @@ zha-quirks==0.0.59
|
|||||||
zigpy-cc==0.5.2
|
zigpy-cc==0.5.2
|
||||||
|
|
||||||
# homeassistant.components.zha
|
# homeassistant.components.zha
|
||||||
zigpy-deconz==0.12.0
|
zigpy-deconz==0.12.1
|
||||||
|
|
||||||
# homeassistant.components.zha
|
# homeassistant.components.zha
|
||||||
zigpy-xbee==0.13.0
|
zigpy-xbee==0.13.0
|
||||||
@ -1359,7 +1359,7 @@ zigpy-xbee==0.13.0
|
|||||||
zigpy-zigate==0.7.3
|
zigpy-zigate==0.7.3
|
||||||
|
|
||||||
# homeassistant.components.zha
|
# homeassistant.components.zha
|
||||||
zigpy-znp==0.5.2
|
zigpy-znp==0.5.3
|
||||||
|
|
||||||
# homeassistant.components.zha
|
# homeassistant.components.zha
|
||||||
zigpy==0.36.1
|
zigpy==0.36.1
|
||||||
|
@ -41,6 +41,7 @@ from homeassistant.const import (
|
|||||||
STATE_ON,
|
STATE_ON,
|
||||||
STATE_UNAVAILABLE,
|
STATE_UNAVAILABLE,
|
||||||
__version__,
|
__version__,
|
||||||
|
__version__ as hass_version,
|
||||||
)
|
)
|
||||||
from homeassistant.helpers.event import TRACK_STATE_CHANGE_CALLBACKS
|
from homeassistant.helpers.event import TRACK_STATE_CHANGE_CALLBACKS
|
||||||
|
|
||||||
@ -130,6 +131,7 @@ async def test_home_accessory(hass, hk_driver):
|
|||||||
serv.get_characteristic(CHAR_SERIAL_NUMBER).value
|
serv.get_characteristic(CHAR_SERIAL_NUMBER).value
|
||||||
== "light.accessory_that_exceeds_the_maximum_maximum_maximum_maximum"
|
== "light.accessory_that_exceeds_the_maximum_maximum_maximum_maximum"
|
||||||
)
|
)
|
||||||
|
assert serv.get_characteristic(CHAR_FIRMWARE_REVISION).value == "0.4.3"
|
||||||
|
|
||||||
hass.states.async_set(entity_id, "on")
|
hass.states.async_set(entity_id, "on")
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
@ -157,6 +159,31 @@ async def test_home_accessory(hass, hk_driver):
|
|||||||
assert serv.get_characteristic(CHAR_MODEL).value == "Test Model"
|
assert serv.get_characteristic(CHAR_MODEL).value == "Test Model"
|
||||||
|
|
||||||
|
|
||||||
|
async def test_accessory_with_missing_basic_service_info(hass, hk_driver):
|
||||||
|
"""Test HomeAccessory class."""
|
||||||
|
entity_id = "sensor.accessory"
|
||||||
|
hass.states.async_set(entity_id, "on")
|
||||||
|
acc = HomeAccessory(
|
||||||
|
hass,
|
||||||
|
hk_driver,
|
||||||
|
"Home Accessory",
|
||||||
|
entity_id,
|
||||||
|
3,
|
||||||
|
{
|
||||||
|
ATTR_MODEL: None,
|
||||||
|
ATTR_MANUFACTURER: None,
|
||||||
|
ATTR_SOFTWARE_VERSION: None,
|
||||||
|
ATTR_INTEGRATION: None,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
serv = acc.get_service(SERV_ACCESSORY_INFO)
|
||||||
|
assert serv.get_characteristic(CHAR_NAME).value == "Home Accessory"
|
||||||
|
assert serv.get_characteristic(CHAR_MANUFACTURER).value == "Home Assistant Sensor"
|
||||||
|
assert serv.get_characteristic(CHAR_MODEL).value == "Sensor"
|
||||||
|
assert serv.get_characteristic(CHAR_SERIAL_NUMBER).value == entity_id
|
||||||
|
assert serv.get_characteristic(CHAR_FIRMWARE_REVISION).value == hass_version
|
||||||
|
|
||||||
|
|
||||||
async def test_battery_service(hass, hk_driver, caplog):
|
async def test_battery_service(hass, hk_driver, caplog):
|
||||||
"""Test battery service."""
|
"""Test battery service."""
|
||||||
entity_id = "homekit.accessory"
|
entity_id = "homekit.accessory"
|
||||||
|
@ -329,7 +329,13 @@ async def test_reset_switch(hass, hk_driver, events):
|
|||||||
future = dt_util.utcnow() + timedelta(seconds=1)
|
future = dt_util.utcnow() + timedelta(seconds=1)
|
||||||
async_fire_time_changed(hass, future)
|
async_fire_time_changed(hass, future)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
assert acc.char_on.value is True
|
||||||
|
|
||||||
|
future = dt_util.utcnow() + timedelta(seconds=10)
|
||||||
|
async_fire_time_changed(hass, future)
|
||||||
|
await hass.async_block_till_done()
|
||||||
assert acc.char_on.value is False
|
assert acc.char_on.value is False
|
||||||
|
|
||||||
assert len(events) == 1
|
assert len(events) == 1
|
||||||
assert not call_turn_off
|
assert not call_turn_off
|
||||||
|
|
||||||
@ -367,7 +373,13 @@ async def test_script_switch(hass, hk_driver, events):
|
|||||||
future = dt_util.utcnow() + timedelta(seconds=1)
|
future = dt_util.utcnow() + timedelta(seconds=1)
|
||||||
async_fire_time_changed(hass, future)
|
async_fire_time_changed(hass, future)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
assert acc.char_on.value is True
|
||||||
|
|
||||||
|
future = dt_util.utcnow() + timedelta(seconds=10)
|
||||||
|
async_fire_time_changed(hass, future)
|
||||||
|
await hass.async_block_till_done()
|
||||||
assert acc.char_on.value is False
|
assert acc.char_on.value is False
|
||||||
|
|
||||||
assert len(events) == 1
|
assert len(events) == 1
|
||||||
assert not call_turn_off
|
assert not call_turn_off
|
||||||
|
|
||||||
|
@ -650,19 +650,30 @@ async def test_merge(merge_log_err, hass):
|
|||||||
"pack_list": {"light": {"platform": "test"}},
|
"pack_list": {"light": {"platform": "test"}},
|
||||||
"pack_list2": {"light": [{"platform": "test"}]},
|
"pack_list2": {"light": [{"platform": "test"}]},
|
||||||
"pack_none": {"wake_on_lan": None},
|
"pack_none": {"wake_on_lan": None},
|
||||||
|
"pack_special": {
|
||||||
|
"automation": [{"some": "yay"}],
|
||||||
|
"script": {"a_script": "yay"},
|
||||||
|
"template": [{"some": "yay"}],
|
||||||
|
},
|
||||||
}
|
}
|
||||||
config = {
|
config = {
|
||||||
config_util.CONF_CORE: {config_util.CONF_PACKAGES: packages},
|
config_util.CONF_CORE: {config_util.CONF_PACKAGES: packages},
|
||||||
"input_boolean": {"ib2": None},
|
"input_boolean": {"ib2": None},
|
||||||
"light": {"platform": "test"},
|
"light": {"platform": "test"},
|
||||||
|
"automation": [],
|
||||||
|
"script": {},
|
||||||
|
"template": [],
|
||||||
}
|
}
|
||||||
await config_util.merge_packages_config(hass, config, packages)
|
await config_util.merge_packages_config(hass, config, packages)
|
||||||
|
|
||||||
assert merge_log_err.call_count == 0
|
assert merge_log_err.call_count == 0
|
||||||
assert len(config) == 5
|
assert len(config) == 8
|
||||||
assert len(config["input_boolean"]) == 2
|
assert len(config["input_boolean"]) == 2
|
||||||
assert len(config["input_select"]) == 1
|
assert len(config["input_select"]) == 1
|
||||||
assert len(config["light"]) == 3
|
assert len(config["light"]) == 3
|
||||||
|
assert len(config["automation"]) == 1
|
||||||
|
assert len(config["script"]) == 1
|
||||||
|
assert len(config["template"]) == 1
|
||||||
assert isinstance(config["wake_on_lan"], OrderedDict)
|
assert isinstance(config["wake_on_lan"], OrderedDict)
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user