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/requirements_all.txt b/requirements_all.txt index 789721caa4a..e94d0c1acae 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -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 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index da71e776f55..8985459f394 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -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 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