mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 21:27:38 +00:00
Merge pull request #66624 from home-assistant/rc
This commit is contained in:
commit
e33671db60
@ -7,8 +7,8 @@
|
||||
"@Bre77"
|
||||
],
|
||||
"requirements": [
|
||||
"advantage_air==0.2.5"
|
||||
"advantage_air==0.3.0"
|
||||
],
|
||||
"quality_scale": "platinum",
|
||||
"iot_class": "local_polling"
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
"config_flow": true,
|
||||
"dependencies": ["network"],
|
||||
"documentation": "https://www.home-assistant.io/integrations/flux_led",
|
||||
"requirements": ["flux_led==0.28.22"],
|
||||
"requirements": ["flux_led==0.28.26"],
|
||||
"quality_scale": "platinum",
|
||||
"codeowners": ["@icemanch", "@bdraco"],
|
||||
"iot_class": "local_push",
|
||||
|
@ -12,10 +12,9 @@ from homeassistant.components.button import (
|
||||
ButtonEntityDescription,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import ENTITY_CATEGORY_CONFIG
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.device_registry import CONNECTION_NETWORK_MAC
|
||||
from homeassistant.helpers.entity import DeviceInfo
|
||||
from homeassistant.helpers.entity import DeviceInfo, EntityCategory
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from .common import AvmWrapper
|
||||
@ -41,28 +40,28 @@ BUTTONS: Final = [
|
||||
key="firmware_update",
|
||||
name="Firmware Update",
|
||||
device_class=ButtonDeviceClass.UPDATE,
|
||||
entity_category=ENTITY_CATEGORY_CONFIG,
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
press_action=lambda avm_wrapper: avm_wrapper.async_trigger_firmware_update(),
|
||||
),
|
||||
FritzButtonDescription(
|
||||
key="reboot",
|
||||
name="Reboot",
|
||||
device_class=ButtonDeviceClass.RESTART,
|
||||
entity_category=ENTITY_CATEGORY_CONFIG,
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
press_action=lambda avm_wrapper: avm_wrapper.async_trigger_reboot(),
|
||||
),
|
||||
FritzButtonDescription(
|
||||
key="reconnect",
|
||||
name="Reconnect",
|
||||
device_class=ButtonDeviceClass.RESTART,
|
||||
entity_category=ENTITY_CATEGORY_CONFIG,
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
press_action=lambda avm_wrapper: avm_wrapper.async_trigger_reconnect(),
|
||||
),
|
||||
FritzButtonDescription(
|
||||
key="cleanup",
|
||||
name="Cleanup",
|
||||
icon="mdi:broom",
|
||||
entity_category=ENTITY_CATEGORY_CONFIG,
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
press_action=lambda avm_wrapper: avm_wrapper.async_trigger_cleanup(),
|
||||
),
|
||||
]
|
||||
|
@ -327,11 +327,19 @@ class FritzBoxTools(update_coordinator.DataUpdateCoordinator):
|
||||
_LOGGER.debug("Checking host info for FRITZ!Box device %s", self.host)
|
||||
self._update_available, self._latest_firmware = self._update_device_info()
|
||||
|
||||
try:
|
||||
topology = self.fritz_hosts.get_mesh_topology()
|
||||
except FritzActionError:
|
||||
self.mesh_role = MeshRoles.SLAVE
|
||||
return
|
||||
if (
|
||||
"Hosts1" not in self.connection.services
|
||||
or "X_AVM-DE_GetMeshListPath"
|
||||
not in self.connection.services["Hosts1"].actions
|
||||
):
|
||||
self.mesh_role = MeshRoles.NONE
|
||||
else:
|
||||
try:
|
||||
topology = self.fritz_hosts.get_mesh_topology()
|
||||
except FritzActionError:
|
||||
self.mesh_role = MeshRoles.SLAVE
|
||||
# Avoid duplicating device trackers
|
||||
return
|
||||
|
||||
_LOGGER.debug("Checking devices for FRITZ!Box device %s", self.host)
|
||||
_default_consider_home = DEFAULT_CONSIDER_HOME.total_seconds()
|
||||
|
@ -13,8 +13,8 @@ from homeassistant.components.binary_sensor import (
|
||||
BinarySensorEntityDescription,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import ENTITY_CATEGORY_CONFIG
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity import EntityCategory
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from . import FritzBoxEntity
|
||||
@ -49,7 +49,7 @@ BINARY_SENSOR_TYPES: Final[tuple[FritzBinarySensorEntityDescription, ...]] = (
|
||||
key="lock",
|
||||
name="Button Lock on Device",
|
||||
device_class=BinarySensorDeviceClass.LOCK,
|
||||
entity_category=ENTITY_CATEGORY_CONFIG,
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
suitable=lambda device: device.lock is not None,
|
||||
is_on=lambda device: not device.lock,
|
||||
),
|
||||
@ -57,7 +57,7 @@ BINARY_SENSOR_TYPES: Final[tuple[FritzBinarySensorEntityDescription, ...]] = (
|
||||
key="device_lock",
|
||||
name="Button Lock via UI",
|
||||
device_class=BinarySensorDeviceClass.LOCK,
|
||||
entity_category=ENTITY_CATEGORY_CONFIG,
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
suitable=lambda device: device.device_lock is not None,
|
||||
is_on=lambda device: not device.device_lock,
|
||||
),
|
||||
|
@ -9,9 +9,9 @@ from goodwe import Inverter, InverterError
|
||||
|
||||
from homeassistant.components.number import NumberEntity, NumberEntityDescription
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import ENTITY_CATEGORY_CONFIG, PERCENTAGE, POWER_WATT
|
||||
from homeassistant.const import PERCENTAGE, POWER_WATT
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity import DeviceInfo
|
||||
from homeassistant.helpers.entity import DeviceInfo, EntityCategory
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from .const import DOMAIN, KEY_DEVICE_INFO, KEY_INVERTER
|
||||
@ -39,7 +39,7 @@ NUMBERS = (
|
||||
key="grid_export_limit",
|
||||
name="Grid export limit",
|
||||
icon="mdi:transmission-tower",
|
||||
entity_category=ENTITY_CATEGORY_CONFIG,
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
unit_of_measurement=POWER_WATT,
|
||||
getter=lambda inv: inv.get_grid_export_limit(),
|
||||
setter=lambda inv, val: inv.set_grid_export_limit(val),
|
||||
@ -51,7 +51,7 @@ NUMBERS = (
|
||||
key="battery_discharge_depth",
|
||||
name="Depth of discharge (on-grid)",
|
||||
icon="mdi:battery-arrow-down",
|
||||
entity_category=ENTITY_CATEGORY_CONFIG,
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
unit_of_measurement=PERCENTAGE,
|
||||
getter=lambda inv: inv.get_ongrid_battery_dod(),
|
||||
setter=lambda inv, val: inv.set_ongrid_battery_dod(val),
|
||||
|
@ -5,9 +5,8 @@ from goodwe import Inverter, InverterError
|
||||
|
||||
from homeassistant.components.select import SelectEntity, SelectEntityDescription
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import ENTITY_CATEGORY_CONFIG
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity import DeviceInfo
|
||||
from homeassistant.helpers.entity import DeviceInfo, EntityCategory
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from .const import DOMAIN, KEY_DEVICE_INFO, KEY_INVERTER
|
||||
@ -26,7 +25,7 @@ OPERATION_MODE = SelectEntityDescription(
|
||||
key="operation_mode",
|
||||
name="Inverter operation mode",
|
||||
icon="mdi:solar-power",
|
||||
entity_category=ENTITY_CATEGORY_CONFIG,
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
)
|
||||
|
||||
|
||||
|
@ -26,7 +26,7 @@ from pycec.const import (
|
||||
|
||||
from homeassistant.components.media_player import MediaPlayerEntity
|
||||
from homeassistant.components.media_player.const import (
|
||||
DOMAIN,
|
||||
DOMAIN as MP_DOMAIN,
|
||||
SUPPORT_NEXT_TRACK,
|
||||
SUPPORT_PAUSE,
|
||||
SUPPORT_PLAY_MEDIA,
|
||||
@ -48,11 +48,11 @@ from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||
|
||||
from . import ATTR_NEW, CecEntity
|
||||
from . import ATTR_NEW, DOMAIN, CecEntity
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
ENTITY_ID_FORMAT = DOMAIN + ".{}"
|
||||
ENTITY_ID_FORMAT = MP_DOMAIN + ".{}"
|
||||
|
||||
|
||||
def setup_platform(
|
||||
@ -77,7 +77,7 @@ class CecPlayerEntity(CecEntity, MediaPlayerEntity):
|
||||
def __init__(self, device, logical) -> None:
|
||||
"""Initialize the HDMI device."""
|
||||
CecEntity.__init__(self, device, logical)
|
||||
self.entity_id = f"{DOMAIN}.hdmi_{hex(self._logical_address)[2:]}"
|
||||
self.entity_id = f"{MP_DOMAIN}.hdmi_{hex(self._logical_address)[2:]}"
|
||||
|
||||
def send_keypress(self, key):
|
||||
"""Send keypress to CEC adapter."""
|
||||
|
@ -3,17 +3,17 @@ from __future__ import annotations
|
||||
|
||||
import logging
|
||||
|
||||
from homeassistant.components.switch import DOMAIN, SwitchEntity
|
||||
from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN, SwitchEntity
|
||||
from homeassistant.const import STATE_OFF, STATE_ON
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||
|
||||
from . import ATTR_NEW, CecEntity
|
||||
from . import ATTR_NEW, DOMAIN, CecEntity
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
ENTITY_ID_FORMAT = DOMAIN + ".{}"
|
||||
ENTITY_ID_FORMAT = SWITCH_DOMAIN + ".{}"
|
||||
|
||||
|
||||
def setup_platform(
|
||||
@ -38,7 +38,7 @@ class CecSwitchEntity(CecEntity, SwitchEntity):
|
||||
def __init__(self, device, logical) -> None:
|
||||
"""Initialize the HDMI device."""
|
||||
CecEntity.__init__(self, device, logical)
|
||||
self.entity_id = f"{DOMAIN}.hdmi_{hex(self._logical_address)[2:]}"
|
||||
self.entity_id = f"{SWITCH_DOMAIN}.hdmi_{hex(self._logical_address)[2:]}"
|
||||
|
||||
def turn_on(self, **kwargs) -> None:
|
||||
"""Turn device on."""
|
||||
|
@ -16,13 +16,12 @@ from homeassistant.const import (
|
||||
DEVICE_CLASS_GAS,
|
||||
DEVICE_CLASS_POWER,
|
||||
ENERGY_KILO_WATT_HOUR,
|
||||
ENTITY_CATEGORY_DIAGNOSTIC,
|
||||
PERCENTAGE,
|
||||
POWER_WATT,
|
||||
VOLUME_CUBIC_METERS,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity import DeviceInfo
|
||||
from homeassistant.helpers.entity import DeviceInfo, EntityCategory
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.typing import StateType
|
||||
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||
@ -37,19 +36,19 @@ SENSORS: Final[tuple[SensorEntityDescription, ...]] = (
|
||||
key="smr_version",
|
||||
name="DSMR Version",
|
||||
icon="mdi:counter",
|
||||
entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
),
|
||||
SensorEntityDescription(
|
||||
key="meter_model",
|
||||
name="Smart Meter Model",
|
||||
icon="mdi:gauge",
|
||||
entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
),
|
||||
SensorEntityDescription(
|
||||
key="wifi_ssid",
|
||||
name="Wifi SSID",
|
||||
icon="mdi:wifi",
|
||||
entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
),
|
||||
SensorEntityDescription(
|
||||
key="wifi_strength",
|
||||
@ -57,7 +56,7 @@ SENSORS: Final[tuple[SensorEntityDescription, ...]] = (
|
||||
icon="mdi:wifi",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
state_class=STATE_CLASS_MEASUREMENT,
|
||||
entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
SensorEntityDescription(
|
||||
|
@ -3,7 +3,7 @@
|
||||
"name": "Philips Hue",
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/hue",
|
||||
"requirements": ["aiohue==4.0.1"],
|
||||
"requirements": ["aiohue==4.1.2"],
|
||||
"ssdp": [
|
||||
{
|
||||
"manufacturer": "Royal Philips Electronics",
|
||||
|
@ -5,7 +5,11 @@ from typing import Any
|
||||
|
||||
from aiohue.v2 import HueBridgeV2
|
||||
from aiohue.v2.controllers.events import EventType
|
||||
from aiohue.v2.controllers.scenes import Scene as HueScene, ScenesController
|
||||
from aiohue.v2.controllers.scenes import (
|
||||
Scene as HueScene,
|
||||
ScenePut as HueScenePut,
|
||||
ScenesController,
|
||||
)
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.scene import ATTR_TRANSITION, Scene as SceneEntity
|
||||
@ -131,7 +135,7 @@ class HueSceneEntity(HueBaseEntity, SceneEntity):
|
||||
await self.bridge.async_request_call(
|
||||
self.controller.update,
|
||||
self.resource.id,
|
||||
HueScene(self.resource.id, speed=speed / 100),
|
||||
HueScenePut(speed=speed / 100),
|
||||
)
|
||||
|
||||
await self.bridge.async_request_call(
|
||||
|
@ -5,8 +5,12 @@ from typing import Any, Union
|
||||
|
||||
from aiohue.v2 import HueBridgeV2
|
||||
from aiohue.v2.controllers.events import EventType
|
||||
from aiohue.v2.controllers.sensors import LightLevelController, MotionController
|
||||
from aiohue.v2.models.resource import SensingService
|
||||
from aiohue.v2.controllers.sensors import (
|
||||
LightLevel,
|
||||
LightLevelController,
|
||||
Motion,
|
||||
MotionController,
|
||||
)
|
||||
|
||||
from homeassistant.components.switch import SwitchDeviceClass, SwitchEntity
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
@ -20,6 +24,8 @@ from .v2.entity import HueBaseEntity
|
||||
|
||||
ControllerType = Union[LightLevelController, MotionController]
|
||||
|
||||
SensingService = Union[LightLevel, Motion]
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
|
@ -4,13 +4,13 @@ from __future__ import annotations
|
||||
from typing import Any, Union
|
||||
|
||||
from aiohue.v2 import HueBridgeV2
|
||||
from aiohue.v2.controllers.config import EntertainmentConfigurationController
|
||||
from aiohue.v2.controllers.config import (
|
||||
EntertainmentConfiguration,
|
||||
EntertainmentConfigurationController,
|
||||
)
|
||||
from aiohue.v2.controllers.events import EventType
|
||||
from aiohue.v2.controllers.sensors import MotionController
|
||||
from aiohue.v2.models.entertainment import (
|
||||
EntertainmentConfiguration,
|
||||
EntertainmentStatus,
|
||||
)
|
||||
from aiohue.v2.models.entertainment_configuration import EntertainmentStatus
|
||||
from aiohue.v2.models.motion import Motion
|
||||
|
||||
from homeassistant.components.binary_sensor import (
|
||||
@ -109,4 +109,4 @@ class HueEntertainmentActiveSensor(HueBinarySensorBase):
|
||||
def name(self) -> str:
|
||||
"""Return sensor name."""
|
||||
type_title = self.resource.type.value.replace("_", " ").title()
|
||||
return f"{self.resource.name}: {type_title}"
|
||||
return f"{self.resource.metadata.name}: {type_title}"
|
||||
|
@ -1,11 +1,12 @@
|
||||
"""Generic Hue Entity Model."""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING, Union
|
||||
|
||||
from aiohue.v2.controllers.base import BaseResourcesController
|
||||
from aiohue.v2.controllers.events import EventType
|
||||
from aiohue.v2.models.clip import CLIPResource
|
||||
from aiohue.v2.models.connectivity import ConnectivityServiceStatus
|
||||
from aiohue.v2.models.resource import ResourceTypes
|
||||
from aiohue.v2.models.zigbee_connectivity import ConnectivityServiceStatus
|
||||
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.helpers.entity import DeviceInfo, Entity
|
||||
@ -14,6 +15,16 @@ from homeassistant.helpers.entity_registry import async_get as async_get_entity_
|
||||
from ..bridge import HueBridge
|
||||
from ..const import CONF_IGNORE_AVAILABILITY, DOMAIN
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from aiohue.v2.models.device_power import DevicePower
|
||||
from aiohue.v2.models.grouped_light import GroupedLight
|
||||
from aiohue.v2.models.light import Light
|
||||
from aiohue.v2.models.light_level import LightLevel
|
||||
from aiohue.v2.models.motion import Motion
|
||||
|
||||
HueResource = Union[Light, DevicePower, GroupedLight, LightLevel, Motion]
|
||||
|
||||
|
||||
RESOURCE_TYPE_NAMES = {
|
||||
# a simple mapping of hue resource type to Hass name
|
||||
ResourceTypes.LIGHT_LEVEL: "Illuminance",
|
||||
@ -30,7 +41,7 @@ class HueBaseEntity(Entity):
|
||||
self,
|
||||
bridge: HueBridge,
|
||||
controller: BaseResourcesController,
|
||||
resource: CLIPResource,
|
||||
resource: HueResource,
|
||||
) -> None:
|
||||
"""Initialize a generic Hue resource entity."""
|
||||
self.bridge = bridge
|
||||
@ -122,7 +133,7 @@ class HueBaseEntity(Entity):
|
||||
# used in subclasses
|
||||
|
||||
@callback
|
||||
def _handle_event(self, event_type: EventType, resource: CLIPResource) -> None:
|
||||
def _handle_event(self, event_type: EventType, resource: HueResource) -> None:
|
||||
"""Handle status event for this resource (or it's parent)."""
|
||||
if event_type == EventType.RESOURCE_DELETED and resource.id == self.resource.id:
|
||||
self.logger.debug("Received delete for %s", self.entity_id)
|
||||
|
@ -7,7 +7,7 @@ from typing import Any
|
||||
from aiohue.v2 import HueBridgeV2
|
||||
from aiohue.v2.controllers.events import EventType
|
||||
from aiohue.v2.controllers.groups import GroupedLight, Room, Zone
|
||||
from aiohue.v2.models.feature import DynamicsFeatureStatus
|
||||
from aiohue.v2.models.feature import DynamicStatus
|
||||
|
||||
from homeassistant.components.light import (
|
||||
ATTR_BRIGHTNESS,
|
||||
@ -283,7 +283,7 @@ class GroupedHueLight(HueBaseEntity, LightEntity):
|
||||
total_brightness += dimming.brightness
|
||||
if (
|
||||
light.dynamics
|
||||
and light.dynamics.status == DynamicsFeatureStatus.DYNAMIC_PALETTE
|
||||
and light.dynamics.status == DynamicStatus.DYNAMIC_PALETTE
|
||||
):
|
||||
lights_in_dynamic_mode += 1
|
||||
|
||||
|
@ -12,10 +12,10 @@ from aiohue.v2.controllers.sensors import (
|
||||
TemperatureController,
|
||||
ZigbeeConnectivityController,
|
||||
)
|
||||
from aiohue.v2.models.connectivity import ZigbeeConnectivity
|
||||
from aiohue.v2.models.device_power import DevicePower
|
||||
from aiohue.v2.models.light_level import LightLevel
|
||||
from aiohue.v2.models.temperature import Temperature
|
||||
from aiohue.v2.models.zigbee_connectivity import ZigbeeConnectivity
|
||||
|
||||
from homeassistant.components.binary_sensor import BinarySensorDeviceClass
|
||||
from homeassistant.components.sensor import (
|
||||
|
@ -8,8 +8,8 @@ write_coil:
|
||||
required: true
|
||||
selector:
|
||||
number:
|
||||
min: 1
|
||||
max: 255
|
||||
min: 0
|
||||
max: 65535
|
||||
state:
|
||||
name: State
|
||||
description: State to write.
|
||||
@ -42,8 +42,8 @@ write_register:
|
||||
required: true
|
||||
selector:
|
||||
number:
|
||||
min: 1
|
||||
max: 255
|
||||
min: 0
|
||||
max: 65535
|
||||
unit:
|
||||
name: Unit
|
||||
description: Address of the modbus unit.
|
||||
|
@ -127,6 +127,15 @@ class NestCamera(Camera):
|
||||
return STREAM_TYPE_WEB_RTC
|
||||
return super().frontend_stream_type
|
||||
|
||||
@property
|
||||
def available(self) -> bool:
|
||||
"""Return True if entity is available."""
|
||||
# Cameras are marked unavailable on stream errors in #54659 however nest streams have
|
||||
# a high error rate (#60353). Given nest streams are so flaky, marking the stream
|
||||
# unavailable has other side effects like not showing the camera image which sometimes
|
||||
# are still able to work. Until the streams are fixed, just leave the streams as available.
|
||||
return True
|
||||
|
||||
async def stream_source(self) -> str | None:
|
||||
"""Return the source of the stream."""
|
||||
if not self.supported_features & SUPPORT_STREAM:
|
||||
|
@ -2,8 +2,8 @@
|
||||
|
||||
from homeassistant.components.button import ButtonDeviceClass, ButtonEntity
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import ENTITY_CATEGORY_CONFIG
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity import EntityCategory
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from .base import ONVIFBaseEntity
|
||||
@ -25,7 +25,7 @@ class RebootButton(ONVIFBaseEntity, ButtonEntity):
|
||||
"""Defines a ONVIF reboot button."""
|
||||
|
||||
_attr_device_class = ButtonDeviceClass.RESTART
|
||||
_attr_entity_category = ENTITY_CATEGORY_CONFIG
|
||||
_attr_entity_category = EntityCategory.CONFIG
|
||||
|
||||
def __init__(self, device: ONVIFDevice) -> None:
|
||||
"""Initialize the button entity."""
|
||||
|
@ -148,9 +148,12 @@ class PhilipsTVDataUpdateCoordinator(DataUpdateCoordinator[None]):
|
||||
@property
|
||||
def unique_id(self) -> str:
|
||||
"""Return the system descriptor."""
|
||||
assert self.config_entry
|
||||
assert self.config_entry.unique_id
|
||||
return self.config_entry.unique_id
|
||||
entry: ConfigEntry = self.config_entry
|
||||
assert entry
|
||||
if entry.unique_id:
|
||||
return entry.unique_id
|
||||
assert entry.entry_id
|
||||
return entry.entry_id
|
||||
|
||||
@property
|
||||
def _notify_wanted(self):
|
||||
|
@ -122,9 +122,9 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
||||
LOGGER.exception("Unexpected exception")
|
||||
errors["base"] = "unknown"
|
||||
else:
|
||||
|
||||
await self.async_set_unique_id(hub.system["serialnumber"])
|
||||
self._abort_if_unique_id_configured()
|
||||
if serialnumber := hub.system.get("serialnumber"):
|
||||
await self.async_set_unique_id(serialnumber)
|
||||
self._abort_if_unique_id_configured()
|
||||
|
||||
self._current[CONF_SYSTEM] = hub.system
|
||||
self._current[CONF_API_VERSION] = hub.api_version
|
||||
|
@ -2,7 +2,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
@ -109,20 +108,12 @@ class I2CHatBinarySensor(BinarySensorEntity):
|
||||
self._device_class = device_class
|
||||
self._state = self.I2C_HATS_MANAGER.read_di(self._address, self._channel)
|
||||
|
||||
async def async_added_to_hass(self) -> None:
|
||||
"""Register callbacks."""
|
||||
if TYPE_CHECKING:
|
||||
assert self.I2C_HATS_MANAGER
|
||||
|
||||
def online_callback():
|
||||
"""Call fired when board is online."""
|
||||
self.schedule_update_ha_state()
|
||||
|
||||
await self.hass.async_add_executor_job(
|
||||
self.I2C_HATS_MANAGER.register_online_callback,
|
||||
self._address,
|
||||
self._channel,
|
||||
online_callback,
|
||||
self.I2C_HATS_MANAGER.register_online_callback(
|
||||
self._address, self._channel, online_callback
|
||||
)
|
||||
|
||||
def edge_callback(state):
|
||||
@ -130,11 +121,8 @@ class I2CHatBinarySensor(BinarySensorEntity):
|
||||
self._state = state
|
||||
self.schedule_update_ha_state()
|
||||
|
||||
await self.hass.async_add_executor_job(
|
||||
self.I2C_HATS_MANAGER.register_di_callback,
|
||||
self._address,
|
||||
self._channel,
|
||||
edge_callback,
|
||||
self.I2C_HATS_MANAGER.register_di_callback(
|
||||
self._address, self._channel, edge_callback
|
||||
)
|
||||
|
||||
@property
|
||||
|
@ -2,7 +2,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
@ -101,7 +100,6 @@ class I2CHatSwitch(SwitchEntity):
|
||||
self._channel = channel
|
||||
self._name = name or DEVICE_DEFAULT_NAME
|
||||
self._invert_logic = invert_logic
|
||||
self._state = initial_state
|
||||
if initial_state is not None:
|
||||
if self._invert_logic:
|
||||
state = not initial_state
|
||||
@ -109,27 +107,14 @@ class I2CHatSwitch(SwitchEntity):
|
||||
state = initial_state
|
||||
self.I2C_HATS_MANAGER.write_dq(self._address, self._channel, state)
|
||||
|
||||
async def async_added_to_hass(self) -> None:
|
||||
"""Register callbacks."""
|
||||
if TYPE_CHECKING:
|
||||
assert self.I2C_HATS_MANAGER
|
||||
def online_callback():
|
||||
"""Call fired when board is online."""
|
||||
self.schedule_update_ha_state()
|
||||
|
||||
await self.hass.async_add_executor_job(
|
||||
self.I2C_HATS_MANAGER.register_online_callback,
|
||||
self._address,
|
||||
self._channel,
|
||||
self.online_callback,
|
||||
self.I2C_HATS_MANAGER.register_online_callback(
|
||||
self._address, self._channel, online_callback
|
||||
)
|
||||
|
||||
def online_callback(self):
|
||||
"""Call fired when board is online."""
|
||||
try:
|
||||
self._state = self.I2C_HATS_MANAGER.read_dq(self._address, self._channel)
|
||||
except I2CHatsException as ex:
|
||||
_LOGGER.error(self._log_message(f"Is ON check failed, {ex!s}"))
|
||||
self._state = False
|
||||
self.schedule_update_ha_state()
|
||||
|
||||
def _log_message(self, message):
|
||||
"""Create log message."""
|
||||
string = f"{self._name} "
|
||||
@ -150,7 +135,12 @@ class I2CHatSwitch(SwitchEntity):
|
||||
@property
|
||||
def is_on(self):
|
||||
"""Return true if device is on."""
|
||||
return self._state != self._invert_logic
|
||||
try:
|
||||
state = self.I2C_HATS_MANAGER.read_dq(self._address, self._channel)
|
||||
return state != self._invert_logic
|
||||
except I2CHatsException as ex:
|
||||
_LOGGER.error(self._log_message(f"Is ON check failed, {ex!s}"))
|
||||
return False
|
||||
|
||||
def turn_on(self, **kwargs):
|
||||
"""Turn the device on."""
|
||||
|
@ -23,7 +23,7 @@ UID_POSTFIX = "01400"
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
_T = TypeVar("_T", "SonosSpeaker", "SonosEntity")
|
||||
_T = TypeVar("_T", bound="SonosSpeaker | SonosEntity")
|
||||
_R = TypeVar("_R")
|
||||
_P = ParamSpec("_P")
|
||||
|
||||
|
@ -3,6 +3,7 @@ from __future__ import annotations
|
||||
|
||||
import datetime
|
||||
import logging
|
||||
from typing import Any
|
||||
|
||||
from soco.exceptions import SoCoException, SoCoSlaveException, SoCoUPnPException
|
||||
|
||||
@ -342,20 +343,20 @@ class SonosAlarmEntity(SonosEntity, SwitchEntity):
|
||||
ATTR_INCLUDE_LINKED_ZONES: self.alarm.include_linked_zones,
|
||||
}
|
||||
|
||||
async def async_turn_on(self, **kwargs) -> None:
|
||||
def turn_on(self, **kwargs: Any) -> None:
|
||||
"""Turn alarm switch on."""
|
||||
await self.async_handle_switch_on_off(turn_on=True)
|
||||
self._handle_switch_on_off(turn_on=True)
|
||||
|
||||
async def async_turn_off(self, **kwargs) -> None:
|
||||
def turn_off(self, **kwargs: Any) -> None:
|
||||
"""Turn alarm switch off."""
|
||||
await self.async_handle_switch_on_off(turn_on=False)
|
||||
self._handle_switch_on_off(turn_on=False)
|
||||
|
||||
async def async_handle_switch_on_off(self, turn_on: bool) -> None:
|
||||
def _handle_switch_on_off(self, turn_on: bool) -> None:
|
||||
"""Handle turn on/off of alarm switch."""
|
||||
try:
|
||||
_LOGGER.debug("Toggling the state of %s", self.entity_id)
|
||||
self.alarm.enabled = turn_on
|
||||
await self.hass.async_add_executor_job(self.alarm.save)
|
||||
self.alarm.save()
|
||||
except (OSError, SoCoException, SoCoUPnPException) as exc:
|
||||
_LOGGER.error("Could not update %s: %s", self.entity_id, exc)
|
||||
|
||||
|
@ -121,6 +121,12 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
raise ConfigEntryNotReady from err
|
||||
|
||||
async def _update_devices() -> list[dict[str, Any]]:
|
||||
if not session.valid_token:
|
||||
await session.async_ensure_token_valid()
|
||||
await hass.async_add_executor_job(
|
||||
spotify.set_auth, session.token["access_token"]
|
||||
)
|
||||
|
||||
try:
|
||||
devices: dict[str, Any] | None = await hass.async_add_executor_job(
|
||||
spotify.devices
|
||||
|
@ -515,9 +515,7 @@ class SpotifyMediaPlayer(MediaPlayerEntity):
|
||||
run_coroutine_threadsafe(
|
||||
self._session.async_ensure_token_valid(), self.hass.loop
|
||||
).result()
|
||||
self._spotify_data[DATA_SPOTIFY_CLIENT] = Spotify(
|
||||
auth=self._session.token["access_token"]
|
||||
)
|
||||
self._spotify.set_auth(auth=self._session.token["access_token"])
|
||||
|
||||
current = self._spotify.current_playback()
|
||||
self._currently_playing = current or {}
|
||||
@ -581,7 +579,11 @@ async def async_browse_media_internal(
|
||||
partial(library_payload, can_play_artist=can_play_artist)
|
||||
)
|
||||
|
||||
await session.async_ensure_token_valid()
|
||||
if not session.valid_token:
|
||||
await session.async_ensure_token_valid()
|
||||
await hass.async_add_executor_job(
|
||||
spotify.set_auth, session.token["access_token"]
|
||||
)
|
||||
|
||||
# Strip prefix
|
||||
media_content_type = media_content_type[len(MEDIA_PLAYER_PREFIX) :]
|
||||
|
@ -342,7 +342,9 @@ class Stream:
|
||||
stream_state.discontinuity()
|
||||
if not self.keepalive or self._thread_quit.is_set():
|
||||
if self._fast_restart_once:
|
||||
# The stream source is updated, restart without any delay.
|
||||
# The stream source is updated, restart without any delay and reset the retry
|
||||
# backoff for the new url.
|
||||
wait_timeout = 0
|
||||
self._fast_restart_once = False
|
||||
self._thread_quit.clear()
|
||||
continue
|
||||
|
@ -8,7 +8,7 @@ DATA_BRIDGE = "bridge"
|
||||
DATA_DEVICE = "device"
|
||||
DATA_DISCOVERY = "discovery"
|
||||
|
||||
DISCOVERY_TIME_SEC = 6
|
||||
DISCOVERY_TIME_SEC = 12
|
||||
|
||||
SIGNAL_DEVICE_ADD = "switcher_device_add"
|
||||
|
||||
@ -19,4 +19,4 @@ SERVICE_SET_AUTO_OFF_NAME = "set_auto_off"
|
||||
SERVICE_TURN_ON_WITH_TIMER_NAME = "turn_on_with_timer"
|
||||
|
||||
# Defines the maximum interval device must send an update before it marked unavailable
|
||||
MAX_UPDATE_INTERVAL_SEC = 20
|
||||
MAX_UPDATE_INTERVAL_SEC = 30
|
||||
|
@ -158,7 +158,10 @@ async def async_setup_entry(
|
||||
device = hass_data.device_manager.device_map[device_id]
|
||||
if descriptions := COVERS.get(device.category):
|
||||
for description in descriptions:
|
||||
if description.key in device.status:
|
||||
if (
|
||||
description.key in device.function
|
||||
or description.key in device.status_range
|
||||
):
|
||||
entities.append(
|
||||
TuyaCoverEntity(
|
||||
device, hass_data.device_manager, description
|
||||
|
@ -182,8 +182,6 @@ class TariffSelect(RestoreEntity):
|
||||
async def async_added_to_hass(self):
|
||||
"""Run when entity about to be added."""
|
||||
await super().async_added_to_hass()
|
||||
if self._current_tariff is not None:
|
||||
return
|
||||
|
||||
state = await self.async_get_last_state()
|
||||
if not state or state.state not in self._tariffs:
|
||||
|
@ -32,6 +32,7 @@ from homeassistant.helpers.event import (
|
||||
async_track_state_change_event,
|
||||
)
|
||||
from homeassistant.helpers.restore_state import RestoreEntity
|
||||
from homeassistant.helpers.template import is_number
|
||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||
import homeassistant.util.dt as dt_util
|
||||
|
||||
@ -166,13 +167,10 @@ class UtilityMeterSensor(RestoreEntity, SensorEntity):
|
||||
self._parent_meter = parent_meter
|
||||
self._sensor_source_id = source_entity
|
||||
self._state = None
|
||||
self._last_period = 0
|
||||
self._last_period = Decimal(0)
|
||||
self._last_reset = dt_util.utcnow()
|
||||
self._collecting = None
|
||||
if name:
|
||||
self._name = name
|
||||
else:
|
||||
self._name = f"{source_entity} meter"
|
||||
self._name = name
|
||||
self._unit_of_measurement = None
|
||||
self._period = meter_type
|
||||
if meter_type is not None:
|
||||
@ -231,8 +229,6 @@ class UtilityMeterSensor(RestoreEntity, SensorEntity):
|
||||
return
|
||||
self._state += adjustment
|
||||
|
||||
except ValueError as err:
|
||||
_LOGGER.warning("While processing state changes: %s", err)
|
||||
except DecimalException as err:
|
||||
_LOGGER.warning(
|
||||
"Invalid state (%s > %s): %s", old_state.state, new_state.state, err
|
||||
@ -282,7 +278,7 @@ class UtilityMeterSensor(RestoreEntity, SensorEntity):
|
||||
return
|
||||
_LOGGER.debug("Reset utility meter <%s>", self.entity_id)
|
||||
self._last_reset = dt_util.utcnow()
|
||||
self._last_period = str(self._state)
|
||||
self._last_period = Decimal(self._state) if self._state else Decimal(0)
|
||||
self._state = 0
|
||||
self.async_write_ha_state()
|
||||
|
||||
@ -319,9 +315,10 @@ class UtilityMeterSensor(RestoreEntity, SensorEntity):
|
||||
ATTR_UNIT_OF_MEASUREMENT
|
||||
)
|
||||
self._last_period = (
|
||||
float(state.attributes.get(ATTR_LAST_PERIOD))
|
||||
Decimal(state.attributes[ATTR_LAST_PERIOD])
|
||||
if state.attributes.get(ATTR_LAST_PERIOD)
|
||||
else 0
|
||||
and is_number(state.attributes[ATTR_LAST_PERIOD])
|
||||
else Decimal(0)
|
||||
)
|
||||
self._last_reset = dt_util.as_utc(
|
||||
dt_util.parse_datetime(state.attributes.get(ATTR_LAST_RESET))
|
||||
@ -399,7 +396,7 @@ class UtilityMeterSensor(RestoreEntity, SensorEntity):
|
||||
state_attr = {
|
||||
ATTR_SOURCE_ID: self._sensor_source_id,
|
||||
ATTR_STATUS: PAUSED if self._collecting is None else COLLECTING,
|
||||
ATTR_LAST_PERIOD: self._last_period,
|
||||
ATTR_LAST_PERIOD: str(self._last_period),
|
||||
}
|
||||
if self._period is not None:
|
||||
state_attr[ATTR_PERIOD] = self._period
|
||||
|
@ -14,8 +14,8 @@ import requests
|
||||
|
||||
from homeassistant.components.button import ButtonEntity, ButtonEntityDescription
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import ENTITY_CATEGORY_CONFIG
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity import EntityCategory
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from . import ViCareRequiredKeysMixin
|
||||
@ -36,7 +36,7 @@ BUTTON_DESCRIPTIONS: tuple[ViCareButtonEntityDescription, ...] = (
|
||||
key=BUTTON_DHW_ACTIVATE_ONETIME_CHARGE,
|
||||
name="Activate one-time charge",
|
||||
icon="mdi:shower-head",
|
||||
entity_category=ENTITY_CATEGORY_CONFIG,
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
value_getter=lambda api: api.activateOneTimeCharge(),
|
||||
),
|
||||
)
|
||||
|
@ -145,7 +145,7 @@ class VizioDevice(MediaPlayerEntity):
|
||||
self._volume_step = config_entry.options[CONF_VOLUME_STEP]
|
||||
self._current_input = None
|
||||
self._current_app_config = None
|
||||
self._app_name = None
|
||||
self._attr_app_name = None
|
||||
self._available_inputs = []
|
||||
self._available_apps = []
|
||||
self._all_apps = apps_coordinator.data if apps_coordinator else None
|
||||
@ -209,7 +209,7 @@ class VizioDevice(MediaPlayerEntity):
|
||||
self._attr_volume_level = None
|
||||
self._attr_is_volume_muted = None
|
||||
self._current_input = None
|
||||
self._app_name = None
|
||||
self._attr_app_name = None
|
||||
self._current_app_config = None
|
||||
self._attr_sound_mode = None
|
||||
return
|
||||
@ -265,13 +265,13 @@ class VizioDevice(MediaPlayerEntity):
|
||||
log_api_exception=False
|
||||
)
|
||||
|
||||
self._app_name = find_app_name(
|
||||
self._attr_app_name = find_app_name(
|
||||
self._current_app_config,
|
||||
[APP_HOME, *self._all_apps, *self._additional_app_configs],
|
||||
)
|
||||
|
||||
if self._app_name == NO_APP_RUNNING:
|
||||
self._app_name = None
|
||||
if self._attr_app_name == NO_APP_RUNNING:
|
||||
self._attr_app_name = None
|
||||
|
||||
def _get_additional_app_names(self) -> list[dict[str, Any]]:
|
||||
"""Return list of additional apps that were included in configuration.yaml."""
|
||||
@ -337,8 +337,8 @@ class VizioDevice(MediaPlayerEntity):
|
||||
@property
|
||||
def source(self) -> str | None:
|
||||
"""Return current input of the device."""
|
||||
if self._app_name is not None and self._current_input in INPUT_APPS:
|
||||
return self._app_name
|
||||
if self._attr_app_name is not None and self._current_input in INPUT_APPS:
|
||||
return self._attr_app_name
|
||||
|
||||
return self._current_input
|
||||
|
||||
@ -364,14 +364,6 @@ class VizioDevice(MediaPlayerEntity):
|
||||
|
||||
return self._available_inputs
|
||||
|
||||
@property
|
||||
def app_name(self) -> str | None:
|
||||
"""Return the name of the current app."""
|
||||
if self.source == self._app_name:
|
||||
return self._app_name
|
||||
|
||||
return None
|
||||
|
||||
@property
|
||||
def app_id(self) -> str | None:
|
||||
"""Return the ID of the current app if it is unknown by pyvizio."""
|
||||
|
@ -8,9 +8,10 @@ from typing import Any
|
||||
|
||||
from homeassistant.components.button import ButtonDeviceClass, ButtonEntity
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import ENTITY_CATEGORY_DIAGNOSTIC, Platform
|
||||
from homeassistant.const import Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||
from homeassistant.helpers.entity import EntityCategory
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from .core import discovery
|
||||
@ -96,7 +97,7 @@ class ZHAIdentifyButton(ZHAButton):
|
||||
return cls(unique_id, zha_device, channels, **kwargs)
|
||||
|
||||
_attr_device_class: ButtonDeviceClass = ButtonDeviceClass.UPDATE
|
||||
_attr_entity_category = ENTITY_CATEGORY_DIAGNOSTIC
|
||||
_attr_entity_category = EntityCategory.DIAGNOSTIC
|
||||
_command_name = "identify"
|
||||
|
||||
def get_args(self) -> list[Any]:
|
||||
|
@ -8,9 +8,10 @@ from zigpy.zcl.clusters.security import IasWd
|
||||
|
||||
from homeassistant.components.select import SelectEntity
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import ENTITY_CATEGORY_CONFIG, STATE_UNKNOWN, Platform
|
||||
from homeassistant.const import STATE_UNKNOWN, Platform
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||
from homeassistant.helpers.entity import EntityCategory
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from .core import discovery
|
||||
@ -46,7 +47,7 @@ async def async_setup_entry(
|
||||
class ZHAEnumSelectEntity(ZhaEntity, SelectEntity):
|
||||
"""Representation of a ZHA select entity."""
|
||||
|
||||
_attr_entity_category = ENTITY_CATEGORY_CONFIG
|
||||
_attr_entity_category = EntityCategory.CONFIG
|
||||
_enum: Enum = None
|
||||
|
||||
def __init__(
|
||||
|
@ -25,7 +25,6 @@ from homeassistant.const import (
|
||||
ELECTRIC_CURRENT_AMPERE,
|
||||
ELECTRIC_POTENTIAL_VOLT,
|
||||
ENERGY_KILO_WATT_HOUR,
|
||||
ENTITY_CATEGORY_DIAGNOSTIC,
|
||||
LIGHT_LUX,
|
||||
PERCENTAGE,
|
||||
POWER_VOLT_AMPERE,
|
||||
@ -699,7 +698,7 @@ class RSSISensor(Sensor, id_suffix="rssi"):
|
||||
|
||||
_state_class: SensorStateClass = SensorStateClass.MEASUREMENT
|
||||
_device_class: SensorDeviceClass = SensorDeviceClass.SIGNAL_STRENGTH
|
||||
_attr_entity_category = ENTITY_CATEGORY_DIAGNOSTIC
|
||||
_attr_entity_category = EntityCategory.DIAGNOSTIC
|
||||
_attr_entity_registry_enabled_default = False
|
||||
|
||||
@classmethod
|
||||
|
@ -7,7 +7,7 @@ from .backports.enum import StrEnum
|
||||
|
||||
MAJOR_VERSION: Final = 2022
|
||||
MINOR_VERSION: Final = 2
|
||||
PATCH_VERSION: Final = "6"
|
||||
PATCH_VERSION: Final = "7"
|
||||
__short_version__: Final = f"{MAJOR_VERSION}.{MINOR_VERSION}"
|
||||
__version__: Final = f"{__short_version__}.{PATCH_VERSION}"
|
||||
REQUIRED_PYTHON_VER: Final[tuple[int, int, int]] = (3, 9, 0)
|
||||
|
@ -114,7 +114,7 @@ adext==0.4.2
|
||||
adguardhome==0.5.1
|
||||
|
||||
# homeassistant.components.advantage_air
|
||||
advantage_air==0.2.5
|
||||
advantage_air==0.3.0
|
||||
|
||||
# homeassistant.components.frontier_silicon
|
||||
afsapi==0.0.4
|
||||
@ -191,7 +191,7 @@ aiohomekit==0.6.11
|
||||
aiohttp_cors==0.7.0
|
||||
|
||||
# homeassistant.components.hue
|
||||
aiohue==4.0.1
|
||||
aiohue==4.1.2
|
||||
|
||||
# homeassistant.components.homewizard
|
||||
aiohwenergy==0.8.0
|
||||
@ -681,7 +681,7 @@ fjaraskupan==1.0.2
|
||||
flipr-api==1.4.1
|
||||
|
||||
# homeassistant.components.flux_led
|
||||
flux_led==0.28.22
|
||||
flux_led==0.28.26
|
||||
|
||||
# homeassistant.components.homekit
|
||||
fnvhash==0.1.0
|
||||
|
@ -70,7 +70,7 @@ adext==0.4.2
|
||||
adguardhome==0.5.1
|
||||
|
||||
# homeassistant.components.advantage_air
|
||||
advantage_air==0.2.5
|
||||
advantage_air==0.3.0
|
||||
|
||||
# homeassistant.components.agent_dvr
|
||||
agent-py==0.0.23
|
||||
@ -141,7 +141,7 @@ aiohomekit==0.6.11
|
||||
aiohttp_cors==0.7.0
|
||||
|
||||
# homeassistant.components.hue
|
||||
aiohue==4.0.1
|
||||
aiohue==4.1.2
|
||||
|
||||
# homeassistant.components.homewizard
|
||||
aiohwenergy==0.8.0
|
||||
@ -427,7 +427,7 @@ fjaraskupan==1.0.2
|
||||
flipr-api==1.4.1
|
||||
|
||||
# homeassistant.components.flux_led
|
||||
flux_led==0.28.22
|
||||
flux_led==0.28.26
|
||||
|
||||
# homeassistant.components.homekit
|
||||
fnvhash==0.1.0
|
||||
|
@ -1,6 +1,6 @@
|
||||
[metadata]
|
||||
name = homeassistant
|
||||
version = 2022.2.6
|
||||
version = 2022.2.7
|
||||
author = The Home Assistant Authors
|
||||
author_email = hello@home-assistant.io
|
||||
license = Apache-2.0
|
||||
|
@ -8,7 +8,6 @@ from unittest.mock import AsyncMock, Mock, patch
|
||||
import aiohue.v1 as aiohue_v1
|
||||
import aiohue.v2 as aiohue_v2
|
||||
from aiohue.v2.controllers.events import EventType
|
||||
from aiohue.v2.models.clip import parse_clip_resource
|
||||
import pytest
|
||||
|
||||
from homeassistant.components import hue
|
||||
@ -187,7 +186,7 @@ def create_mock_api_v2(hass):
|
||||
|
||||
def emit_event(event_type, data):
|
||||
"""Emit an event from a (hue resource) dict."""
|
||||
api.events.emit(EventType(event_type), parse_clip_resource(data))
|
||||
api.events.emit(EventType(event_type), data)
|
||||
|
||||
api.load_test_data = load_test_data
|
||||
api.emit_event = emit_event
|
||||
|
@ -97,8 +97,12 @@ async def test_light_turn_on_service(hass, mock_bridge_v2, v2_resources_test_dat
|
||||
assert mock_bridge_v2.mock_requests[0]["json"]["color_temperature"]["mirek"] == 300
|
||||
|
||||
# Now generate update event by emitting the json we've sent as incoming event
|
||||
mock_bridge_v2.mock_requests[0]["json"]["color_temperature"].pop("mirek_valid")
|
||||
mock_bridge_v2.api.emit_event("update", mock_bridge_v2.mock_requests[0]["json"])
|
||||
event = {
|
||||
"id": "3a6710fa-4474-4eba-b533-5e6e72968feb",
|
||||
"type": "light",
|
||||
**mock_bridge_v2.mock_requests[0]["json"],
|
||||
}
|
||||
mock_bridge_v2.api.emit_event("update", event)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# the light should now be on
|
||||
@ -186,7 +190,12 @@ async def test_light_turn_off_service(hass, mock_bridge_v2, v2_resources_test_da
|
||||
assert mock_bridge_v2.mock_requests[0]["json"]["on"]["on"] is False
|
||||
|
||||
# Now generate update event by emitting the json we've sent as incoming event
|
||||
mock_bridge_v2.api.emit_event("update", mock_bridge_v2.mock_requests[0]["json"])
|
||||
event = {
|
||||
"id": "02cba059-9c2c-4d45-97e4-4f79b1bfbaa1",
|
||||
"type": "light",
|
||||
**mock_bridge_v2.mock_requests[0]["json"],
|
||||
}
|
||||
mock_bridge_v2.api.emit_event("update", event)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# the light should now be off
|
||||
@ -377,10 +386,20 @@ async def test_grouped_lights(hass, mock_bridge_v2, v2_resources_test_data):
|
||||
)
|
||||
|
||||
# Now generate update events by emitting the json we've sent as incoming events
|
||||
for index in range(0, 3):
|
||||
mock_bridge_v2.api.emit_event(
|
||||
"update", mock_bridge_v2.mock_requests[index]["json"]
|
||||
)
|
||||
for index, light_id in enumerate(
|
||||
[
|
||||
"02cba059-9c2c-4d45-97e4-4f79b1bfbaa1",
|
||||
"b3fe71ef-d0ef-48de-9355-d9e604377df0",
|
||||
"8015b17f-8336-415b-966a-b364bd082397",
|
||||
]
|
||||
):
|
||||
event = {
|
||||
"id": light_id,
|
||||
"type": "light",
|
||||
**mock_bridge_v2.mock_requests[index]["json"],
|
||||
}
|
||||
mock_bridge_v2.api.emit_event("update", event)
|
||||
await hass.async_block_till_done()
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# the light should now be on and have the properties we've set
|
||||
@ -406,6 +425,12 @@ async def test_grouped_lights(hass, mock_bridge_v2, v2_resources_test_data):
|
||||
assert mock_bridge_v2.mock_requests[0]["json"]["on"]["on"] is False
|
||||
|
||||
# Now generate update event by emitting the json we've sent as incoming event
|
||||
event = {
|
||||
"id": "f2416154-9607-43ab-a684-4453108a200e",
|
||||
"type": "grouped_light",
|
||||
**mock_bridge_v2.mock_requests[0]["json"],
|
||||
}
|
||||
mock_bridge_v2.api.emit_event("update", event)
|
||||
mock_bridge_v2.api.emit_event("update", mock_bridge_v2.mock_requests[0]["json"])
|
||||
await hass.async_block_till_done()
|
||||
|
||||
|
@ -69,7 +69,12 @@ async def test_switch_turn_off_service(hass, mock_bridge_v2, v2_resources_test_d
|
||||
assert mock_bridge_v2.mock_requests[0]["json"]["enabled"] is False
|
||||
|
||||
# Now generate update event by emitting the json we've sent as incoming event
|
||||
mock_bridge_v2.api.emit_event("update", mock_bridge_v2.mock_requests[0]["json"])
|
||||
event = {
|
||||
"id": "b6896534-016d-4052-8cb4-ef04454df62c",
|
||||
"type": "motion",
|
||||
**mock_bridge_v2.mock_requests[0]["json"],
|
||||
}
|
||||
mock_bridge_v2.api.emit_event("update", event)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# the switch should now be off
|
||||
|
@ -62,7 +62,12 @@ async def test_services(hass):
|
||||
"source": "sensor.energy",
|
||||
"cycle": "hourly",
|
||||
"tariffs": ["peak", "offpeak"],
|
||||
}
|
||||
},
|
||||
"energy_bill2": {
|
||||
"source": "sensor.energy",
|
||||
"cycle": "hourly",
|
||||
"tariffs": ["peak", "offpeak"],
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@ -153,6 +158,10 @@ async def test_services(hass):
|
||||
state = hass.states.get("sensor.energy_bill_offpeak")
|
||||
assert state.state == "0"
|
||||
|
||||
# meanwhile energy_bill2_peak accumulated all kWh
|
||||
state = hass.states.get("sensor.energy_bill2_peak")
|
||||
assert state.state == "4"
|
||||
|
||||
|
||||
async def test_cron(hass, legacy_patchable_time):
|
||||
"""Test cron pattern and offset fails."""
|
||||
|
@ -304,6 +304,10 @@ async def test_restore_state(hass):
|
||||
ATTR_UNIT_OF_MEASUREMENT: ENERGY_KILO_WATT_HOUR,
|
||||
},
|
||||
),
|
||||
State(
|
||||
"sensor.energy_bill_midpeak",
|
||||
"error",
|
||||
),
|
||||
State(
|
||||
"sensor.energy_bill_offpeak",
|
||||
"6",
|
||||
@ -326,6 +330,9 @@ async def test_restore_state(hass):
|
||||
assert state.attributes.get("last_reset") == last_reset
|
||||
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == ENERGY_KILO_WATT_HOUR
|
||||
|
||||
state = hass.states.get("sensor.energy_bill_midpeak")
|
||||
assert state.state == STATE_UNKNOWN
|
||||
|
||||
state = hass.states.get("sensor.energy_bill_offpeak")
|
||||
assert state.state == "6"
|
||||
assert state.attributes.get("status") == COLLECTING
|
||||
@ -530,7 +537,7 @@ async def _test_self_reset(hass, config, start_time, expect_reset=True):
|
||||
assert state.attributes.get("last_reset") == now.isoformat()
|
||||
assert state.state == "3"
|
||||
else:
|
||||
assert state.attributes.get("last_period") == 0
|
||||
assert state.attributes.get("last_period") == "0"
|
||||
assert state.state == "5"
|
||||
start_time_str = dt_util.parse_datetime(start_time).isoformat()
|
||||
assert state.attributes.get("last_reset") == start_time_str
|
||||
@ -559,7 +566,7 @@ async def _test_self_reset(hass, config, start_time, expect_reset=True):
|
||||
assert state.attributes.get("last_period") == "2"
|
||||
assert state.state == "7"
|
||||
else:
|
||||
assert state.attributes.get("last_period") == 0
|
||||
assert state.attributes.get("last_period") == "0"
|
||||
assert state.state == "9"
|
||||
|
||||
|
||||
|
@ -764,6 +764,5 @@ async def test_vizio_update_with_apps_on_input(
|
||||
)
|
||||
await _add_config_entry_to_hass(hass, config_entry)
|
||||
attr = _get_attr_and_assert_base_attr(hass, DEVICE_CLASS_TV, STATE_ON)
|
||||
# App name and app ID should not be in the attributes
|
||||
assert "app_name" not in attr
|
||||
# app ID should not be in the attributes
|
||||
assert "app_id" not in attr
|
||||
|
Loading…
x
Reference in New Issue
Block a user