diff --git a/homeassistant/components/advantage_air/manifest.json b/homeassistant/components/advantage_air/manifest.json index 6390ccea39c..56c89fe7346 100644 --- a/homeassistant/components/advantage_air/manifest.json +++ b/homeassistant/components/advantage_air/manifest.json @@ -7,8 +7,8 @@ "@Bre77" ], "requirements": [ - "advantage_air==0.2.5" + "advantage_air==0.3.0" ], "quality_scale": "platinum", "iot_class": "local_polling" -} \ No newline at end of file +} diff --git a/homeassistant/components/flux_led/manifest.json b/homeassistant/components/flux_led/manifest.json index 40661f27bab..17c73200619 100644 --- a/homeassistant/components/flux_led/manifest.json +++ b/homeassistant/components/flux_led/manifest.json @@ -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", diff --git a/homeassistant/components/fritz/button.py b/homeassistant/components/fritz/button.py index d17d1f4d9ef..e72af839e4c 100644 --- a/homeassistant/components/fritz/button.py +++ b/homeassistant/components/fritz/button.py @@ -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(), ), ] diff --git a/homeassistant/components/fritz/common.py b/homeassistant/components/fritz/common.py index ae506989e00..b005e536ed6 100644 --- a/homeassistant/components/fritz/common.py +++ b/homeassistant/components/fritz/common.py @@ -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() diff --git a/homeassistant/components/fritzbox/binary_sensor.py b/homeassistant/components/fritzbox/binary_sensor.py index b58f3311cb5..b80d853e562 100644 --- a/homeassistant/components/fritzbox/binary_sensor.py +++ b/homeassistant/components/fritzbox/binary_sensor.py @@ -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, ), diff --git a/homeassistant/components/goodwe/number.py b/homeassistant/components/goodwe/number.py index 06a31a4e10a..80c7885f26c 100644 --- a/homeassistant/components/goodwe/number.py +++ b/homeassistant/components/goodwe/number.py @@ -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), diff --git a/homeassistant/components/goodwe/select.py b/homeassistant/components/goodwe/select.py index 985c799110d..c8fa44b7e26 100644 --- a/homeassistant/components/goodwe/select.py +++ b/homeassistant/components/goodwe/select.py @@ -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, ) diff --git a/homeassistant/components/hdmi_cec/media_player.py b/homeassistant/components/hdmi_cec/media_player.py index c31daa85316..9ee705c1c5e 100644 --- a/homeassistant/components/hdmi_cec/media_player.py +++ b/homeassistant/components/hdmi_cec/media_player.py @@ -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.""" diff --git a/homeassistant/components/hdmi_cec/switch.py b/homeassistant/components/hdmi_cec/switch.py index 8e6deae1394..a5d64b2a7fa 100644 --- a/homeassistant/components/hdmi_cec/switch.py +++ b/homeassistant/components/hdmi_cec/switch.py @@ -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.""" diff --git a/homeassistant/components/homewizard/sensor.py b/homeassistant/components/homewizard/sensor.py index c2a11386cf4..e9a09f9db86 100644 --- a/homeassistant/components/homewizard/sensor.py +++ b/homeassistant/components/homewizard/sensor.py @@ -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( diff --git a/homeassistant/components/hue/manifest.json b/homeassistant/components/hue/manifest.json index 12f7df13866..a21a3ace72b 100644 --- a/homeassistant/components/hue/manifest.json +++ b/homeassistant/components/hue/manifest.json @@ -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", diff --git a/homeassistant/components/hue/scene.py b/homeassistant/components/hue/scene.py index 3d1967ecff3..8e894b4e295 100644 --- a/homeassistant/components/hue/scene.py +++ b/homeassistant/components/hue/scene.py @@ -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( diff --git a/homeassistant/components/hue/switch.py b/homeassistant/components/hue/switch.py index 7f8e048d692..7fb40cba38f 100644 --- a/homeassistant/components/hue/switch.py +++ b/homeassistant/components/hue/switch.py @@ -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, diff --git a/homeassistant/components/hue/v2/binary_sensor.py b/homeassistant/components/hue/v2/binary_sensor.py index 47617b45af6..a7077ccf765 100644 --- a/homeassistant/components/hue/v2/binary_sensor.py +++ b/homeassistant/components/hue/v2/binary_sensor.py @@ -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}" diff --git a/homeassistant/components/hue/v2/entity.py b/homeassistant/components/hue/v2/entity.py index c8c2f9e423b..721425606bc 100644 --- a/homeassistant/components/hue/v2/entity.py +++ b/homeassistant/components/hue/v2/entity.py @@ -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) diff --git a/homeassistant/components/hue/v2/group.py b/homeassistant/components/hue/v2/group.py index 300f08727ba..31c5a502853 100644 --- a/homeassistant/components/hue/v2/group.py +++ b/homeassistant/components/hue/v2/group.py @@ -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 diff --git a/homeassistant/components/hue/v2/sensor.py b/homeassistant/components/hue/v2/sensor.py index ff2b7b78e7d..d331393d29b 100644 --- a/homeassistant/components/hue/v2/sensor.py +++ b/homeassistant/components/hue/v2/sensor.py @@ -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 ( diff --git a/homeassistant/components/modbus/services.yaml b/homeassistant/components/modbus/services.yaml index 835927e4627..87e8b98fa21 100644 --- a/homeassistant/components/modbus/services.yaml +++ b/homeassistant/components/modbus/services.yaml @@ -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. diff --git a/homeassistant/components/nest/camera_sdm.py b/homeassistant/components/nest/camera_sdm.py index fca79bde040..858561dd3ea 100644 --- a/homeassistant/components/nest/camera_sdm.py +++ b/homeassistant/components/nest/camera_sdm.py @@ -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: diff --git a/homeassistant/components/onvif/button.py b/homeassistant/components/onvif/button.py index 034573299e6..23ea5124e61 100644 --- a/homeassistant/components/onvif/button.py +++ b/homeassistant/components/onvif/button.py @@ -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.""" diff --git a/homeassistant/components/philips_js/__init__.py b/homeassistant/components/philips_js/__init__.py index 1292310f134..9a317726768 100644 --- a/homeassistant/components/philips_js/__init__.py +++ b/homeassistant/components/philips_js/__init__.py @@ -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): diff --git a/homeassistant/components/philips_js/config_flow.py b/homeassistant/components/philips_js/config_flow.py index 89f13ffadbf..29abbe5dd71 100644 --- a/homeassistant/components/philips_js/config_flow.py +++ b/homeassistant/components/philips_js/config_flow.py @@ -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 diff --git a/homeassistant/components/raspihats/binary_sensor.py b/homeassistant/components/raspihats/binary_sensor.py index 2c0ce10a5f3..f8fbc0d010f 100644 --- a/homeassistant/components/raspihats/binary_sensor.py +++ b/homeassistant/components/raspihats/binary_sensor.py @@ -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 diff --git a/homeassistant/components/raspihats/switch.py b/homeassistant/components/raspihats/switch.py index 0e05e376ed4..8ca88528543 100644 --- a/homeassistant/components/raspihats/switch.py +++ b/homeassistant/components/raspihats/switch.py @@ -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.""" diff --git a/homeassistant/components/sonos/helpers.py b/homeassistant/components/sonos/helpers.py index 625b54b941e..6da25314f0f 100644 --- a/homeassistant/components/sonos/helpers.py +++ b/homeassistant/components/sonos/helpers.py @@ -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") diff --git a/homeassistant/components/sonos/switch.py b/homeassistant/components/sonos/switch.py index 4e3303db45d..2ee8af61327 100644 --- a/homeassistant/components/sonos/switch.py +++ b/homeassistant/components/sonos/switch.py @@ -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) diff --git a/homeassistant/components/spotify/__init__.py b/homeassistant/components/spotify/__init__.py index c3e9504c05c..446c2ace82c 100644 --- a/homeassistant/components/spotify/__init__.py +++ b/homeassistant/components/spotify/__init__.py @@ -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 diff --git a/homeassistant/components/spotify/media_player.py b/homeassistant/components/spotify/media_player.py index b3bb2efd1c0..06efb5558d1 100644 --- a/homeassistant/components/spotify/media_player.py +++ b/homeassistant/components/spotify/media_player.py @@ -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) :] diff --git a/homeassistant/components/stream/__init__.py b/homeassistant/components/stream/__init__.py index 79506c0bda2..731fd410686 100644 --- a/homeassistant/components/stream/__init__.py +++ b/homeassistant/components/stream/__init__.py @@ -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 diff --git a/homeassistant/components/switcher_kis/const.py b/homeassistant/components/switcher_kis/const.py index 88b6e447446..fdd5b02fe9b 100644 --- a/homeassistant/components/switcher_kis/const.py +++ b/homeassistant/components/switcher_kis/const.py @@ -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 diff --git a/homeassistant/components/tuya/cover.py b/homeassistant/components/tuya/cover.py index 6a9e3767065..de277e61510 100644 --- a/homeassistant/components/tuya/cover.py +++ b/homeassistant/components/tuya/cover.py @@ -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 diff --git a/homeassistant/components/utility_meter/__init__.py b/homeassistant/components/utility_meter/__init__.py index bf9beae060c..525b4f3b43c 100644 --- a/homeassistant/components/utility_meter/__init__.py +++ b/homeassistant/components/utility_meter/__init__.py @@ -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: diff --git a/homeassistant/components/utility_meter/sensor.py b/homeassistant/components/utility_meter/sensor.py index b65628d5f0b..ec137968bc5 100644 --- a/homeassistant/components/utility_meter/sensor.py +++ b/homeassistant/components/utility_meter/sensor.py @@ -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 diff --git a/homeassistant/components/vicare/button.py b/homeassistant/components/vicare/button.py index 35133b55bd1..e924a735e0f 100644 --- a/homeassistant/components/vicare/button.py +++ b/homeassistant/components/vicare/button.py @@ -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(), ), ) diff --git a/homeassistant/components/vizio/media_player.py b/homeassistant/components/vizio/media_player.py index e9cd89c635a..664a8ae7da8 100644 --- a/homeassistant/components/vizio/media_player.py +++ b/homeassistant/components/vizio/media_player.py @@ -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.""" diff --git a/homeassistant/components/zha/button.py b/homeassistant/components/zha/button.py index 90148ba42f3..abfa94f5906 100644 --- a/homeassistant/components/zha/button.py +++ b/homeassistant/components/zha/button.py @@ -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]: diff --git a/homeassistant/components/zha/select.py b/homeassistant/components/zha/select.py index ff76023d96d..7cb214566d1 100644 --- a/homeassistant/components/zha/select.py +++ b/homeassistant/components/zha/select.py @@ -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__( diff --git a/homeassistant/components/zha/sensor.py b/homeassistant/components/zha/sensor.py index eb79634695f..1e7d4f28a38 100644 --- a/homeassistant/components/zha/sensor.py +++ b/homeassistant/components/zha/sensor.py @@ -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 diff --git a/homeassistant/const.py b/homeassistant/const.py index 13250b3f9e5..c206a4f3f7a 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -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) diff --git a/requirements_all.txt b/requirements_all.txt index b524400e811..e94d0c1acae 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -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 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 358a1d21748..8985459f394 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -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 diff --git a/setup.cfg b/setup.cfg index c912d68ed55..a9634ea3b6f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -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 diff --git a/tests/components/hue/conftest.py b/tests/components/hue/conftest.py index 9e9ed9af31b..d0d15d320e0 100644 --- a/tests/components/hue/conftest.py +++ b/tests/components/hue/conftest.py @@ -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 diff --git a/tests/components/hue/test_light_v2.py b/tests/components/hue/test_light_v2.py index c7578df3a49..f0265233e4e 100644 --- a/tests/components/hue/test_light_v2.py +++ b/tests/components/hue/test_light_v2.py @@ -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() diff --git a/tests/components/hue/test_switch.py b/tests/components/hue/test_switch.py index 257f1a253c3..e8086709705 100644 --- a/tests/components/hue/test_switch.py +++ b/tests/components/hue/test_switch.py @@ -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 diff --git a/tests/components/utility_meter/test_init.py b/tests/components/utility_meter/test_init.py index 61e6fc4dae8..3297c696ca1 100644 --- a/tests/components/utility_meter/test_init.py +++ b/tests/components/utility_meter/test_init.py @@ -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.""" diff --git a/tests/components/utility_meter/test_sensor.py b/tests/components/utility_meter/test_sensor.py index 51212580aaf..fbaf795f9e2 100644 --- a/tests/components/utility_meter/test_sensor.py +++ b/tests/components/utility_meter/test_sensor.py @@ -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" diff --git a/tests/components/vizio/test_media_player.py b/tests/components/vizio/test_media_player.py index d3ef4019c57..80f72280951 100644 --- a/tests/components/vizio/test_media_player.py +++ b/tests/components/vizio/test_media_player.py @@ -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