mirror of
https://github.com/home-assistant/core.git
synced 2026-02-15 07:36:16 +00:00
Add LED control for supported UniFi network devices (#152649)
This commit is contained in:
committed by
GitHub
parent
1d6c6628f4
commit
681eb6b594
@@ -13,6 +13,7 @@ PLATFORMS = [
|
||||
Platform.BUTTON,
|
||||
Platform.DEVICE_TRACKER,
|
||||
Platform.IMAGE,
|
||||
Platform.LIGHT,
|
||||
Platform.SENSOR,
|
||||
Platform.SWITCH,
|
||||
Platform.UPDATE,
|
||||
|
||||
172
homeassistant/components/unifi/light.py
Normal file
172
homeassistant/components/unifi/light.py
Normal file
@@ -0,0 +1,172 @@
|
||||
"""Light platform for UniFi Network integration."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Callable, Coroutine
|
||||
from dataclasses import dataclass
|
||||
from typing import TYPE_CHECKING, Any, cast
|
||||
|
||||
from aiounifi.interfaces.api_handlers import APIHandler, ItemEvent
|
||||
from aiounifi.interfaces.devices import Devices
|
||||
from aiounifi.models.api import ApiItem
|
||||
from aiounifi.models.device import Device, DeviceSetLedStatus
|
||||
|
||||
from homeassistant.components.light import (
|
||||
ATTR_BRIGHTNESS,
|
||||
ATTR_RGB_COLOR,
|
||||
ColorMode,
|
||||
LightEntity,
|
||||
LightEntityDescription,
|
||||
LightEntityFeature,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
||||
from homeassistant.util.color import rgb_hex_to_rgb_list
|
||||
|
||||
from . import UnifiConfigEntry
|
||||
from .entity import (
|
||||
UnifiEntity,
|
||||
UnifiEntityDescription,
|
||||
async_device_available_fn,
|
||||
async_device_device_info_fn,
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .hub import UnifiHub
|
||||
|
||||
|
||||
@callback
|
||||
def async_device_led_supported_fn(hub: UnifiHub, obj_id: str) -> bool:
|
||||
"""Check if device supports LED control."""
|
||||
device: Device = hub.api.devices[obj_id]
|
||||
return device.supports_led_ring
|
||||
|
||||
|
||||
@callback
|
||||
def async_device_led_is_on_fn(hub: UnifiHub, device: Device) -> bool:
|
||||
"""Check if device LED is on."""
|
||||
return device.led_override == "on"
|
||||
|
||||
|
||||
async def async_device_led_control_fn(
|
||||
hub: UnifiHub, obj_id: str, turn_on: bool, **kwargs: Any
|
||||
) -> None:
|
||||
"""Control device LED."""
|
||||
device = hub.api.devices[obj_id]
|
||||
|
||||
status = "on" if turn_on else "off"
|
||||
|
||||
brightness = (
|
||||
int((kwargs[ATTR_BRIGHTNESS] / 255) * 100)
|
||||
if ATTR_BRIGHTNESS in kwargs
|
||||
else device.led_override_color_brightness
|
||||
)
|
||||
|
||||
color = (
|
||||
f"#{kwargs[ATTR_RGB_COLOR][0]:02x}{kwargs[ATTR_RGB_COLOR][1]:02x}{kwargs[ATTR_RGB_COLOR][2]:02x}"
|
||||
if ATTR_RGB_COLOR in kwargs
|
||||
else device.led_override_color
|
||||
)
|
||||
|
||||
await hub.api.request(
|
||||
DeviceSetLedStatus.create(
|
||||
device=device,
|
||||
status=status,
|
||||
brightness=brightness,
|
||||
color=color,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@dataclass(frozen=True, kw_only=True)
|
||||
class UnifiLightEntityDescription[HandlerT: APIHandler, ApiItemT: ApiItem](
|
||||
LightEntityDescription, UnifiEntityDescription[HandlerT, ApiItemT]
|
||||
):
|
||||
"""Class describing UniFi light entity."""
|
||||
|
||||
control_fn: Callable[[UnifiHub, str, bool], Coroutine[Any, Any, None]]
|
||||
is_on_fn: Callable[[UnifiHub, ApiItemT], bool]
|
||||
|
||||
|
||||
ENTITY_DESCRIPTIONS: tuple[UnifiLightEntityDescription, ...] = (
|
||||
UnifiLightEntityDescription[Devices, Device](
|
||||
key="LED control",
|
||||
translation_key="led_control",
|
||||
allowed_fn=lambda hub, obj_id: True,
|
||||
api_handler_fn=lambda api: api.devices,
|
||||
available_fn=async_device_available_fn,
|
||||
control_fn=async_device_led_control_fn,
|
||||
device_info_fn=async_device_device_info_fn,
|
||||
is_on_fn=async_device_led_is_on_fn,
|
||||
name_fn=lambda device: "LED",
|
||||
object_fn=lambda api, obj_id: api.devices[obj_id],
|
||||
supported_fn=async_device_led_supported_fn,
|
||||
unique_id_fn=lambda hub, obj_id: f"led-{obj_id}",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
config_entry: UnifiConfigEntry,
|
||||
async_add_entities: AddConfigEntryEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up lights for UniFi Network integration."""
|
||||
config_entry.runtime_data.entity_loader.register_platform(
|
||||
async_add_entities,
|
||||
UnifiLightEntity,
|
||||
ENTITY_DESCRIPTIONS,
|
||||
requires_admin=True,
|
||||
)
|
||||
|
||||
|
||||
class UnifiLightEntity[HandlerT: APIHandler, ApiItemT: ApiItem](
|
||||
UnifiEntity[HandlerT, ApiItemT], LightEntity
|
||||
):
|
||||
"""Base representation of a UniFi light."""
|
||||
|
||||
entity_description: UnifiLightEntityDescription[HandlerT, ApiItemT]
|
||||
_attr_supported_features = LightEntityFeature(0)
|
||||
_attr_color_mode = ColorMode.RGB
|
||||
_attr_supported_color_modes = {ColorMode.RGB}
|
||||
|
||||
@callback
|
||||
def async_initiate_state(self) -> None:
|
||||
"""Initiate entity state."""
|
||||
self.async_update_state(ItemEvent.ADDED, self._obj_id)
|
||||
|
||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||
"""Turn on light."""
|
||||
await self.entity_description.control_fn(self.hub, self._obj_id, True, **kwargs)
|
||||
|
||||
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||
"""Turn off light."""
|
||||
await self.entity_description.control_fn(
|
||||
self.hub, self._obj_id, False, **kwargs
|
||||
)
|
||||
|
||||
@callback
|
||||
def async_update_state(self, event: ItemEvent, obj_id: str) -> None:
|
||||
"""Update entity state."""
|
||||
description = self.entity_description
|
||||
device_obj = description.object_fn(self.api, self._obj_id)
|
||||
|
||||
device = cast(Device, device_obj)
|
||||
|
||||
self._attr_is_on = description.is_on_fn(self.hub, device_obj)
|
||||
|
||||
brightness = device.led_override_color_brightness
|
||||
self._attr_brightness = (
|
||||
int((int(brightness) / 100) * 255) if brightness is not None else None
|
||||
)
|
||||
|
||||
hex_color = (
|
||||
device.led_override_color.lstrip("#")
|
||||
if self._attr_is_on and device.led_override_color
|
||||
else None
|
||||
)
|
||||
if hex_color and len(hex_color) == 6:
|
||||
rgb_list = rgb_hex_to_rgb_list(hex_color)
|
||||
self._attr_rgb_color = (rgb_list[0], rgb_list[1], rgb_list[2])
|
||||
else:
|
||||
self._attr_rgb_color = None
|
||||
@@ -34,6 +34,11 @@
|
||||
}
|
||||
},
|
||||
"entity": {
|
||||
"light": {
|
||||
"led_control": {
|
||||
"name": "LED"
|
||||
}
|
||||
},
|
||||
"sensor": {
|
||||
"device_state": {
|
||||
"state": {
|
||||
|
||||
72
tests/components/unifi/snapshots/test_light.ambr
Normal file
72
tests/components/unifi/snapshots/test_light.ambr
Normal file
@@ -0,0 +1,72 @@
|
||||
# serializer version: 1
|
||||
# name: test_light_platform_snapshot[device_payload0][light.device_with_led_led-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': dict({
|
||||
'supported_color_modes': list([
|
||||
<ColorMode.RGB: 'rgb'>,
|
||||
]),
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'light',
|
||||
'entity_category': None,
|
||||
'entity_id': 'light.device_with_led_led',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': 'LED',
|
||||
'platform': 'unifi',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'led_control',
|
||||
'unique_id': 'led-10:00:00:00:01:01',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_light_platform_snapshot[device_payload0][light.device_with_led_led-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'brightness': 204,
|
||||
'color_mode': <ColorMode.RGB: 'rgb'>,
|
||||
'friendly_name': 'Device with LED LED',
|
||||
'hs_color': tuple(
|
||||
240.0,
|
||||
100.0,
|
||||
),
|
||||
'rgb_color': tuple(
|
||||
0,
|
||||
0,
|
||||
255,
|
||||
),
|
||||
'supported_color_modes': list([
|
||||
<ColorMode.RGB: 'rgb'>,
|
||||
]),
|
||||
'supported_features': <LightEntityFeature: 0>,
|
||||
'xy_color': tuple(
|
||||
0.136,
|
||||
0.04,
|
||||
),
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'light.device_with_led_led',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'on',
|
||||
})
|
||||
# ---
|
||||
@@ -41,6 +41,7 @@ async def test_hub_setup(
|
||||
Platform.BUTTON,
|
||||
Platform.DEVICE_TRACKER,
|
||||
Platform.IMAGE,
|
||||
Platform.LIGHT,
|
||||
Platform.SENSOR,
|
||||
Platform.SWITCH,
|
||||
Platform.UPDATE,
|
||||
|
||||
323
tests/components/unifi/test_light.py
Normal file
323
tests/components/unifi/test_light.py
Normal file
@@ -0,0 +1,323 @@
|
||||
"""UniFi Network light platform tests."""
|
||||
|
||||
from copy import deepcopy
|
||||
from unittest.mock import patch
|
||||
|
||||
from aiounifi.models.message import MessageKey
|
||||
import pytest
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
|
||||
from homeassistant.components.light import (
|
||||
ATTR_BRIGHTNESS,
|
||||
ATTR_RGB_COLOR,
|
||||
DOMAIN as LIGHT_DOMAIN,
|
||||
SERVICE_TURN_OFF,
|
||||
SERVICE_TURN_ON,
|
||||
)
|
||||
from homeassistant.components.unifi.const import CONF_SITE_ID
|
||||
from homeassistant.const import (
|
||||
ATTR_ENTITY_ID,
|
||||
CONF_HOST,
|
||||
STATE_OFF,
|
||||
STATE_ON,
|
||||
STATE_UNAVAILABLE,
|
||||
Platform,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
from .conftest import (
|
||||
ConfigEntryFactoryType,
|
||||
WebsocketMessageMock,
|
||||
WebsocketStateManager,
|
||||
)
|
||||
|
||||
from tests.common import MockConfigEntry, snapshot_platform
|
||||
from tests.test_util.aiohttp import AiohttpClientMocker
|
||||
|
||||
DEVICE_WITH_LED = {
|
||||
"board_rev": 3,
|
||||
"device_id": "mock-id",
|
||||
"ip": "10.0.0.1",
|
||||
"last_seen": 1562600145,
|
||||
"mac": "10:00:00:00:01:01",
|
||||
"model": "U6-Lite",
|
||||
"name": "Device with LED",
|
||||
"next_interval": 20,
|
||||
"state": 1,
|
||||
"type": "uap",
|
||||
"version": "4.0.42.10433",
|
||||
"led_override": "on",
|
||||
"led_override_color": "#0000ff",
|
||||
"led_override_color_brightness": 80,
|
||||
"hw_caps": 2,
|
||||
}
|
||||
|
||||
DEVICE_WITHOUT_LED = {
|
||||
"board_rev": 2,
|
||||
"device_id": "mock-id-2",
|
||||
"ip": "10.0.0.2",
|
||||
"last_seen": 1562600145,
|
||||
"mac": "10:00:00:00:01:02",
|
||||
"model": "US-8-60W",
|
||||
"name": "Device without LED",
|
||||
"next_interval": 20,
|
||||
"state": 1,
|
||||
"type": "usw",
|
||||
"version": "4.0.42.10433",
|
||||
"hw_caps": 0,
|
||||
}
|
||||
|
||||
DEVICE_LED_OFF = {
|
||||
"board_rev": 3,
|
||||
"device_id": "mock-id-3",
|
||||
"ip": "10.0.0.3",
|
||||
"last_seen": 1562600145,
|
||||
"mac": "10:00:00:00:01:03",
|
||||
"model": "U6-Pro",
|
||||
"name": "Device LED Off",
|
||||
"next_interval": 20,
|
||||
"state": 1,
|
||||
"type": "uap",
|
||||
"version": "4.0.42.10433",
|
||||
"led_override": "off",
|
||||
"led_override_color": "#ffffff",
|
||||
"led_override_color_brightness": 0,
|
||||
"hw_caps": 2,
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize("device_payload", [[DEVICE_WITH_LED, DEVICE_WITHOUT_LED]])
|
||||
@pytest.mark.usefixtures("config_entry_setup")
|
||||
async def test_lights(
|
||||
hass: HomeAssistant,
|
||||
aioclient_mock: AiohttpClientMocker,
|
||||
config_entry_setup: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Test lights."""
|
||||
assert len(hass.states.async_entity_ids(LIGHT_DOMAIN)) == 1
|
||||
|
||||
light_entity = hass.states.get("light.device_with_led_led")
|
||||
assert light_entity is not None
|
||||
assert light_entity.state == STATE_ON
|
||||
assert light_entity.attributes["brightness"] == 204
|
||||
assert light_entity.attributes["rgb_color"] == (0, 0, 255)
|
||||
|
||||
assert hass.states.get("light.device_without_led_led") is None
|
||||
|
||||
|
||||
@pytest.mark.parametrize("device_payload", [[DEVICE_LED_OFF]])
|
||||
@pytest.mark.usefixtures("config_entry_setup")
|
||||
async def test_light_off_state(
|
||||
hass: HomeAssistant,
|
||||
) -> None:
|
||||
"""Test light off state."""
|
||||
assert len(hass.states.async_entity_ids(LIGHT_DOMAIN)) == 1
|
||||
|
||||
light_entity = hass.states.get("light.device_led_off_led")
|
||||
assert light_entity is not None
|
||||
assert light_entity.state == STATE_OFF
|
||||
assert light_entity.attributes.get("brightness") is None
|
||||
assert light_entity.attributes.get("rgb_color") is None
|
||||
|
||||
|
||||
@pytest.mark.parametrize("device_payload", [[DEVICE_WITH_LED]])
|
||||
@pytest.mark.usefixtures("config_entry_setup")
|
||||
async def test_light_turn_on_off(
|
||||
hass: HomeAssistant,
|
||||
aioclient_mock: AiohttpClientMocker,
|
||||
config_entry_setup: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Test turn on and off."""
|
||||
aioclient_mock.clear_requests()
|
||||
aioclient_mock.put(
|
||||
f"https://{config_entry_setup.data[CONF_HOST]}:1234"
|
||||
f"/api/s/{config_entry_setup.data[CONF_SITE_ID]}/rest/device/mock-id",
|
||||
)
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
SERVICE_TURN_OFF,
|
||||
{ATTR_ENTITY_ID: "light.device_with_led_led"},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
assert aioclient_mock.call_count == 1
|
||||
call_data = aioclient_mock.mock_calls[0][2]
|
||||
assert call_data["led_override"] == "off"
|
||||
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
SERVICE_TURN_ON,
|
||||
{ATTR_ENTITY_ID: "light.device_with_led_led"},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
assert aioclient_mock.call_count == 2
|
||||
call_data = aioclient_mock.mock_calls[1][2]
|
||||
assert call_data["led_override"] == "on"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("device_payload", [[DEVICE_WITH_LED]])
|
||||
@pytest.mark.usefixtures("config_entry_setup")
|
||||
async def test_light_set_brightness(
|
||||
hass: HomeAssistant,
|
||||
aioclient_mock: AiohttpClientMocker,
|
||||
config_entry_setup: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Test set brightness."""
|
||||
aioclient_mock.clear_requests()
|
||||
aioclient_mock.put(
|
||||
f"https://{config_entry_setup.data[CONF_HOST]}:1234"
|
||||
f"/api/s/{config_entry_setup.data[CONF_SITE_ID]}/rest/device/mock-id",
|
||||
)
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
SERVICE_TURN_ON,
|
||||
{
|
||||
ATTR_ENTITY_ID: "light.device_with_led_led",
|
||||
ATTR_BRIGHTNESS: 127,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
assert aioclient_mock.call_count == 1
|
||||
call_data = aioclient_mock.mock_calls[0][2]
|
||||
assert call_data["led_override"] == "on"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("device_payload", [[DEVICE_WITH_LED]])
|
||||
@pytest.mark.usefixtures("config_entry_setup")
|
||||
async def test_light_set_rgb_color(
|
||||
hass: HomeAssistant,
|
||||
aioclient_mock: AiohttpClientMocker,
|
||||
config_entry_setup: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Test set RGB color."""
|
||||
aioclient_mock.clear_requests()
|
||||
aioclient_mock.put(
|
||||
f"https://{config_entry_setup.data[CONF_HOST]}:1234"
|
||||
f"/api/s/{config_entry_setup.data[CONF_SITE_ID]}/rest/device/mock-id",
|
||||
)
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
SERVICE_TURN_ON,
|
||||
{
|
||||
ATTR_ENTITY_ID: "light.device_with_led_led",
|
||||
ATTR_RGB_COLOR: (255, 0, 0),
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
assert aioclient_mock.call_count == 1
|
||||
call_data = aioclient_mock.mock_calls[0][2]
|
||||
assert call_data["led_override"] == "on"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("device_payload", [[DEVICE_WITH_LED]])
|
||||
@pytest.mark.usefixtures("config_entry_setup")
|
||||
async def test_light_set_brightness_and_color(
|
||||
hass: HomeAssistant,
|
||||
aioclient_mock: AiohttpClientMocker,
|
||||
config_entry_setup: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Test set brightness and color."""
|
||||
aioclient_mock.clear_requests()
|
||||
aioclient_mock.put(
|
||||
f"https://{config_entry_setup.data[CONF_HOST]}:1234"
|
||||
f"/api/s/{config_entry_setup.data[CONF_SITE_ID]}/rest/device/mock-id",
|
||||
)
|
||||
await hass.services.async_call(
|
||||
LIGHT_DOMAIN,
|
||||
SERVICE_TURN_ON,
|
||||
{
|
||||
ATTR_ENTITY_ID: "light.device_with_led_led",
|
||||
ATTR_RGB_COLOR: (0, 255, 0),
|
||||
ATTR_BRIGHTNESS: 191,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
assert aioclient_mock.call_count == 1
|
||||
call_data = aioclient_mock.mock_calls[0][2]
|
||||
assert call_data["led_override"] == "on"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("device_payload", [[DEVICE_WITH_LED]])
|
||||
@pytest.mark.usefixtures("config_entry_setup")
|
||||
async def test_light_state_update_via_websocket(
|
||||
hass: HomeAssistant,
|
||||
mock_websocket_message: WebsocketMessageMock,
|
||||
) -> None:
|
||||
"""Test state update via websocket."""
|
||||
light_entity = hass.states.get("light.device_with_led_led")
|
||||
assert light_entity is not None
|
||||
assert light_entity.state == STATE_ON
|
||||
assert light_entity.attributes["rgb_color"] == (0, 0, 255)
|
||||
updated_device = deepcopy(DEVICE_WITH_LED)
|
||||
updated_device["led_override"] = "off"
|
||||
updated_device["led_override_color"] = "#ff0000"
|
||||
updated_device["led_override_color_brightness"] = 100
|
||||
|
||||
mock_websocket_message(message=MessageKey.DEVICE, data=[updated_device])
|
||||
await hass.async_block_till_done()
|
||||
|
||||
light_entity = hass.states.get("light.device_with_led_led")
|
||||
assert light_entity is not None
|
||||
assert light_entity.state == STATE_OFF
|
||||
assert light_entity.attributes.get("rgb_color") is None
|
||||
assert light_entity.attributes.get("brightness") is None
|
||||
|
||||
|
||||
@pytest.mark.parametrize("device_payload", [[DEVICE_WITH_LED]])
|
||||
@pytest.mark.usefixtures("config_entry_setup")
|
||||
async def test_light_device_offline(
|
||||
hass: HomeAssistant,
|
||||
mock_websocket_message: WebsocketMessageMock,
|
||||
) -> None:
|
||||
"""Test device offline."""
|
||||
assert len(hass.states.async_entity_ids(LIGHT_DOMAIN)) == 1
|
||||
assert hass.states.get("light.device_with_led_led") is not None
|
||||
|
||||
offline_device = deepcopy(DEVICE_WITH_LED)
|
||||
offline_device["state"] = 0
|
||||
mock_websocket_message(message=MessageKey.DEVICE, data=[offline_device])
|
||||
await hass.async_block_till_done()
|
||||
|
||||
light_entity = hass.states.get("light.device_with_led_led")
|
||||
assert light_entity is not None
|
||||
assert light_entity.state == STATE_ON
|
||||
|
||||
|
||||
@pytest.mark.parametrize("device_payload", [[DEVICE_WITH_LED]])
|
||||
@pytest.mark.usefixtures("config_entry_setup")
|
||||
async def test_light_device_unavailable(
|
||||
hass: HomeAssistant,
|
||||
mock_websocket_state: WebsocketStateManager,
|
||||
) -> None:
|
||||
"""Test device unavailable."""
|
||||
light_entity = hass.states.get("light.device_with_led_led")
|
||||
assert light_entity is not None
|
||||
assert light_entity.state == STATE_ON
|
||||
|
||||
updated_device = deepcopy(DEVICE_WITH_LED)
|
||||
updated_device["state"] = 0
|
||||
|
||||
await mock_websocket_state.disconnect()
|
||||
await hass.async_block_till_done()
|
||||
|
||||
light_entity = hass.states.get("light.device_with_led_led")
|
||||
assert light_entity is not None
|
||||
assert light_entity.state == STATE_UNAVAILABLE
|
||||
|
||||
|
||||
@pytest.mark.parametrize("device_payload", [[DEVICE_WITH_LED]])
|
||||
async def test_light_platform_snapshot(
|
||||
hass: HomeAssistant,
|
||||
entity_registry: er.EntityRegistry,
|
||||
config_entry_factory: ConfigEntryFactoryType,
|
||||
snapshot: SnapshotAssertion,
|
||||
) -> None:
|
||||
"""Test platform snapshot."""
|
||||
with patch("homeassistant.components.unifi.PLATFORMS", [Platform.LIGHT]):
|
||||
config_entry = await config_entry_factory()
|
||||
await snapshot_platform(hass, entity_registry, snapshot, config_entry.entry_id)
|
||||
Reference in New Issue
Block a user