Skip to content

Commit

Permalink
Add scene support to WMS WebControl pro
Browse files Browse the repository at this point in the history
  • Loading branch information
mback2k committed Sep 22, 2024
1 parent b107b2c commit 1359fc9
Show file tree
Hide file tree
Showing 6 changed files with 181 additions and 2 deletions.
2 changes: 1 addition & 1 deletion homeassistant/components/wmspro/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

from .const import DOMAIN, MANUFACTURER

PLATFORMS: list[Platform] = [Platform.COVER]
PLATFORMS: list[Platform] = [Platform.COVER, Platform.SCENE]

type WebControlProConfigEntry = ConfigEntry[WebControlPro]

Expand Down
60 changes: 60 additions & 0 deletions homeassistant/components/wmspro/scene.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
"""Support for scenes provided by WMS WebControl pro."""

from __future__ import annotations

from typing import Any

from wmspro.scene import Scene as WMS_Scene

from homeassistant.components.scene import Scene
from homeassistant.core import HomeAssistant
from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback

from . import WebControlProConfigEntry
from .const import ATTRIBUTION, DOMAIN, MANUFACTURER


async def async_setup_entry(
hass: HomeAssistant,
config_entry: WebControlProConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up the WMS based scenes from a config entry."""
hub = config_entry.runtime_data

entities: list[WebControlProScene] = [
WebControlProScene(config_entry.entry_id, scene)
for scene in hub.scenes.values()
]

async_add_entities(entities)


class WebControlProScene(Scene):
"""Representation of a WMS based scene."""

_attr_attribution = ATTRIBUTION
_attr_has_entity_name = True
_attr_name = None

def __init__(self, config_entry_id: str, scene: WMS_Scene) -> None:
"""Initialize the entity with the configured scene."""
super().__init__()
scene_id_str = str(scene.id)
self._scene = scene
self._attr_unique_id = scene_id_str
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, scene_id_str)},
manufacturer=MANUFACTURER,
model="Scene",
name=scene.name,
serial_number=scene_id_str,
suggested_area=scene.room.name,
via_device=(DOMAIN, config_entry_id),
configuration_url=f"http://{scene.host}/control",
)

async def async_activate(self, **kwargs: Any) -> None:
"""Activate scene. Try to get entities into requested state."""
await self._scene()
9 changes: 9 additions & 0 deletions tests/components/wmspro/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,12 @@ async def fake_call(self, **kwargs):
fake_call,
) as mock_action_call:
yield mock_action_call


@pytest.fixture
def mock_scene_call() -> Generator[AsyncMock]:
"""Override Scene.__call__."""
with patch(
"wmspro.scene.Scene.__call__",
) as mock_scene_call:
yield mock_scene_call
47 changes: 47 additions & 0 deletions tests/components/wmspro/snapshots/test_scene.ambr
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# serializer version: 1
# name: test_scene_activate
StateSnapshot({
'attributes': ReadOnlyDict({
'attribution': 'Data provided by WMS WebControl pro API',
'friendly_name': 'Gute Nacht',
}),
'context': <ANY>,
'entity_id': 'scene.gute_nacht',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'unknown',
})
# ---
# name: test_scene_device
DeviceRegistryEntrySnapshot({
'area_id': 'raum_0',
'config_entries': <ANY>,
'configuration_url': 'http://webcontrol/control',
'connections': set({
}),
'disabled_by': None,
'entry_type': None,
'hw_version': None,
'id': <ANY>,
'identifiers': set({
tuple(
'wmspro',
'688966',
),
}),
'is_new': False,
'labels': set({
}),
'manufacturer': 'WAREMA Renkhoff SE',
'model': 'Scene',
'model_id': None,
'name': 'Gute Nacht',
'name_by_user': None,
'primary_config_entry': <ANY>,
'serial_number': '688966',
'suggested_area': 'Raum 0',
'sw_version': None,
'via_device_id': <ANY>,
})
# ---
2 changes: 1 addition & 1 deletion tests/components/wmspro/test_cover.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""Test the wmspro diagnostics."""
"""Test the wmspro cover support."""

from unittest.mock import AsyncMock, patch

Expand Down
63 changes: 63 additions & 0 deletions tests/components/wmspro/test_scene.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
"""Test the wmspro scene support."""

from unittest.mock import AsyncMock

from syrupy import SnapshotAssertion

from homeassistant.components.wmspro.const import DOMAIN
from homeassistant.const import ATTR_ENTITY_ID, SERVICE_TURN_ON
from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry as dr
from homeassistant.setup import async_setup_component

from . import setup_config_entry

from tests.common import MockConfigEntry


async def test_scene_device(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_hub_ping: AsyncMock,
mock_hub_configuration_test: AsyncMock,
mock_dest_refresh: AsyncMock,
device_registry: dr.DeviceRegistry,
snapshot: SnapshotAssertion,
) -> None:
"""Test that a scene device is created correctly."""
assert await setup_config_entry(hass, mock_config_entry)
assert len(mock_hub_ping.mock_calls) == 1
assert len(mock_hub_configuration_test.mock_calls) == 1

device_entry = device_registry.async_get_device(identifiers={(DOMAIN, "688966")})
assert device_entry is not None
assert device_entry == snapshot


async def test_scene_activate(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_hub_ping: AsyncMock,
mock_hub_configuration_test: AsyncMock,
mock_dest_refresh: AsyncMock,
mock_scene_call: AsyncMock,
snapshot: SnapshotAssertion,
) -> None:
"""Test that a scene entity is created and activated correctly."""
assert await setup_config_entry(hass, mock_config_entry)
assert len(mock_hub_ping.mock_calls) == 1
assert len(mock_hub_configuration_test.mock_calls) == 1

entity = hass.states.get("scene.gute_nacht")
assert entity is not None
assert entity == snapshot

await async_setup_component(hass, "homeassistant", {})
await hass.services.async_call(
"homeassistant",
SERVICE_TURN_ON,
{ATTR_ENTITY_ID: entity.entity_id},
blocking=True,
)

assert len(mock_scene_call.mock_calls) == 1

0 comments on commit 1359fc9

Please sign in to comment.