mirror of
https://github.com/home-assistant/core.git
synced 2026-07-13 17:44:45 +01:00
Add first cover entity tests to Overkiz (#165670)
Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
@@ -1,14 +1,16 @@
|
||||
"""Tests for the overkiz component."""
|
||||
"""Tests for the Overkiz component."""
|
||||
|
||||
import humps
|
||||
from pyoverkiz.models import Setup
|
||||
|
||||
from homeassistant.components.overkiz.const import DOMAIN
|
||||
|
||||
from tests.common import load_json_object_fixture
|
||||
|
||||
DEFAULT_SETUP_FIXTURE = "setup/cloud_somfy_tahoma_switch_europe.json"
|
||||
|
||||
def load_setup_fixture(
|
||||
fixture: str = "overkiz/setup/setup_tahoma_switch.json",
|
||||
) -> Setup:
|
||||
|
||||
def load_setup_fixture(fixture: str = DEFAULT_SETUP_FIXTURE) -> Setup:
|
||||
"""Return setup from fixture."""
|
||||
setup_json = load_json_object_fixture(fixture)
|
||||
setup_json = load_json_object_fixture(fixture, DOMAIN)
|
||||
return Setup(**humps.decamelize(setup_json))
|
||||
|
||||
@@ -1,19 +1,92 @@
|
||||
"""Configuration for overkiz tests."""
|
||||
|
||||
from collections.abc import Generator
|
||||
from unittest.mock import AsyncMock, Mock, patch
|
||||
from collections.abc import Awaitable, Callable, Generator
|
||||
from dataclasses import dataclass, field
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
from pyoverkiz.client import OverkizClient
|
||||
from pyoverkiz.enums import APIType
|
||||
from pyoverkiz.models import Event, OverkizServer, Setup
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.overkiz.const import DOMAIN
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from . import load_setup_fixture
|
||||
from . import DEFAULT_SETUP_FIXTURE, load_setup_fixture
|
||||
from .test_config_flow import TEST_EMAIL, TEST_GATEWAY_ID, TEST_PASSWORD, TEST_SERVER
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
MOCK_SETUP_RESPONSE = Mock(devices=[], gateways=[])
|
||||
type SetupOverkizIntegration = Callable[..., Awaitable[MockConfigEntry]]
|
||||
|
||||
|
||||
@dataclass
|
||||
class MockOverkizClient(OverkizClient):
|
||||
"""Mock Overkiz client used by integration tests."""
|
||||
|
||||
setup: Setup = field(default_factory=load_setup_fixture)
|
||||
event_batches: list[list[Event]] = field(default_factory=list)
|
||||
server: OverkizServer = field(
|
||||
default_factory=lambda: OverkizServer(
|
||||
name="Somfy",
|
||||
endpoint="https://example.test/enduser-mobile-web/enduserAPI",
|
||||
manufacturer="Somfy",
|
||||
configuration_url=None,
|
||||
)
|
||||
)
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
"""Initialize async client methods."""
|
||||
self._execution_id = 0
|
||||
self.api_type = APIType.CLOUD
|
||||
self.login = AsyncMock(return_value=True)
|
||||
self.get_setup = AsyncMock(side_effect=self._async_get_setup)
|
||||
self.get_devices = AsyncMock(side_effect=self._async_get_devices)
|
||||
self.get_scenarios = AsyncMock(return_value=[])
|
||||
self.fetch_events = AsyncMock(side_effect=self._async_fetch_events)
|
||||
self.get_current_executions = AsyncMock(return_value=[])
|
||||
self.cancel_command = AsyncMock(return_value=None)
|
||||
self.execute_command = AsyncMock(side_effect=self._async_execute_command)
|
||||
|
||||
def set_setup_fixture(self, fixture: str) -> None:
|
||||
"""Load a setup fixture for the next integration setup."""
|
||||
self.setup = load_setup_fixture(fixture)
|
||||
self.event_batches.clear()
|
||||
self.reset_mock()
|
||||
|
||||
def queue_events(self, *batches: list[Event]) -> None:
|
||||
"""Queue batches of events returned by fetch_events."""
|
||||
self.event_batches.extend(batches)
|
||||
|
||||
def reset_mock(self) -> None:
|
||||
"""Reset call history while keeping configured behavior."""
|
||||
self.login.reset_mock()
|
||||
self.get_setup.reset_mock()
|
||||
self.get_devices.reset_mock()
|
||||
self.get_scenarios.reset_mock()
|
||||
self.fetch_events.reset_mock()
|
||||
self.get_current_executions.reset_mock()
|
||||
self.cancel_command.reset_mock()
|
||||
self.execute_command.reset_mock()
|
||||
|
||||
async def _async_get_setup(self) -> Setup:
|
||||
"""Return the configured setup."""
|
||||
return self.setup
|
||||
|
||||
async def _async_get_devices(self, refresh: bool = False) -> list:
|
||||
"""Return the configured devices."""
|
||||
return self.setup.devices
|
||||
|
||||
async def _async_fetch_events(self) -> list[Event]:
|
||||
"""Return queued event batches one refresh at a time."""
|
||||
if self.event_batches:
|
||||
return self.event_batches.pop(0)
|
||||
return []
|
||||
|
||||
async def _async_execute_command(self, *args, **kwargs) -> str:
|
||||
"""Return a unique execution id for each command."""
|
||||
self._execution_id += 1
|
||||
return f"exec-{self._execution_id}"
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@@ -37,21 +110,48 @@ def mock_setup_entry() -> Generator[AsyncMock]:
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def init_integration(
|
||||
def mock_client() -> MockOverkizClient:
|
||||
"""Return a configurable mock Overkiz client."""
|
||||
return MockOverkizClient()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def setup_overkiz_integration(
|
||||
hass: HomeAssistant,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
mock_client: MockOverkizClient,
|
||||
) -> SetupOverkizIntegration:
|
||||
"""Return a helper to set up the Overkiz integration from a chosen fixture."""
|
||||
|
||||
async def _setup(
|
||||
*,
|
||||
fixture: str = DEFAULT_SETUP_FIXTURE,
|
||||
) -> MockConfigEntry:
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
|
||||
mock_client.set_setup_fixture(fixture)
|
||||
|
||||
with (
|
||||
patch(
|
||||
"homeassistant.components.overkiz.create_cloud_client",
|
||||
return_value=mock_client,
|
||||
),
|
||||
patch(
|
||||
"homeassistant.components.overkiz.create_local_client",
|
||||
return_value=mock_client,
|
||||
),
|
||||
):
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
return mock_config_entry
|
||||
|
||||
return _setup
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def init_integration(
|
||||
setup_overkiz_integration: SetupOverkizIntegration,
|
||||
) -> MockConfigEntry:
|
||||
"""Set up the Overkiz integration for testing."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
|
||||
with patch.multiple(
|
||||
"pyoverkiz.client.OverkizClient",
|
||||
login=AsyncMock(return_value=True),
|
||||
get_setup=AsyncMock(return_value=load_setup_fixture()),
|
||||
get_scenarios=AsyncMock(return_value=[]),
|
||||
fetch_events=AsyncMock(return_value=[]),
|
||||
):
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
return mock_config_entry
|
||||
return await setup_overkiz_integration()
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,345 @@
|
||||
{
|
||||
"creationTime": 1613674982000,
|
||||
"lastUpdateTime": 1613674982000,
|
||||
"id": "SETUP-1234-1234-6362",
|
||||
"location": {
|
||||
"creationTime": 1613674982000,
|
||||
"lastUpdateTime": 1632527573000,
|
||||
"city": "*",
|
||||
"country": "*",
|
||||
"postalCode": "*/*",
|
||||
"addressLine1": "*",
|
||||
"addressLine2": "",
|
||||
"timezone": "Asia/Bangkok",
|
||||
"longitude": "*",
|
||||
"latitude": "*",
|
||||
"twilightMode": 2,
|
||||
"twilightAngle": "CIVIL",
|
||||
"twilightCity": "paris",
|
||||
"summerSolsticeDuskMinutes": 1290,
|
||||
"winterSolsticeDuskMinutes": 990,
|
||||
"twilightOffsetEnabled": false,
|
||||
"dawnOffset": 0,
|
||||
"duskOffset": 0,
|
||||
"countryCode": "TH"
|
||||
},
|
||||
"gateways": [
|
||||
{
|
||||
"gatewayId": "1234-1234-6362",
|
||||
"type": 53,
|
||||
"subType": 1,
|
||||
"placeOID": "6133b4a0-f514-4553-b635-d1b7beb7e7b2",
|
||||
"alive": true,
|
||||
"timeReliable": true,
|
||||
"connectivity": {
|
||||
"status": "OK",
|
||||
"protocolVersion": "2021.2.4"
|
||||
},
|
||||
"upToDate": true,
|
||||
"updateStatus": "UP_TO_DATE",
|
||||
"syncInProgress": false,
|
||||
"functions": "INTERNET_AUTHORIZATION,SCENARIO_DOWNLOAD,SCENARIO_AUTO_LAUNCHING,SCENARIO_TELECO_LAUNCHING,INTERNET_UPLOAD,INTERNET_UPDATE,TRIGGERS_SENSORS",
|
||||
"mode": "ACTIVE"
|
||||
}
|
||||
],
|
||||
"devices": [
|
||||
{
|
||||
"creationTime": 1613675393000,
|
||||
"lastUpdateTime": 1613675393000,
|
||||
"label": "*",
|
||||
"deviceURL": "internal://1234-1234-6362/pod/0",
|
||||
"shortcut": false,
|
||||
"controllableName": "internal:PodMiniComponent",
|
||||
"definition": {
|
||||
"commands": [
|
||||
{
|
||||
"commandName": "getName",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"commandName": "update",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"commandName": "setCountryCode",
|
||||
"nparams": 1
|
||||
},
|
||||
{
|
||||
"commandName": "activateCalendar",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"commandName": "deactivateCalendar",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"commandName": "refreshPodMode",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"commandName": "refreshUpdateStatus",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"commandName": "setCalendar",
|
||||
"nparams": 1
|
||||
},
|
||||
{
|
||||
"commandName": "setLightingLedPodMode",
|
||||
"nparams": 1
|
||||
},
|
||||
{
|
||||
"commandName": "setPodLedOff",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"commandName": "setPodLedOn",
|
||||
"nparams": 0
|
||||
}
|
||||
],
|
||||
"states": [
|
||||
{
|
||||
"type": "DiscreteState",
|
||||
"values": ["offline", "online"],
|
||||
"qualifiedName": "core:ConnectivityState"
|
||||
},
|
||||
{
|
||||
"type": "DataState",
|
||||
"qualifiedName": "core:CountryCodeState"
|
||||
},
|
||||
{
|
||||
"type": "DataState",
|
||||
"qualifiedName": "core:LocalIPv4AddressState"
|
||||
},
|
||||
{
|
||||
"type": "DataState",
|
||||
"qualifiedName": "core:NameState"
|
||||
},
|
||||
{
|
||||
"type": "DiscreteState",
|
||||
"values": [
|
||||
"doublePress",
|
||||
"longPress",
|
||||
"simplePress",
|
||||
"triplePress",
|
||||
"veryLongPress"
|
||||
],
|
||||
"qualifiedName": "internal:LastActionConfigButtonState"
|
||||
},
|
||||
{
|
||||
"type": "ContinuousState",
|
||||
"qualifiedName": "internal:LightingLedPodModeState"
|
||||
}
|
||||
],
|
||||
"dataProperties": [],
|
||||
"widgetName": "Pod",
|
||||
"uiProfiles": ["UpdatableComponent"],
|
||||
"uiClass": "Pod",
|
||||
"qualifiedName": "internal:PodMiniComponent",
|
||||
"type": "ACTUATOR"
|
||||
},
|
||||
"states": [
|
||||
{
|
||||
"name": "core:NameState",
|
||||
"type": 3,
|
||||
"value": "*"
|
||||
},
|
||||
{
|
||||
"name": "internal:LightingLedPodModeState",
|
||||
"type": 2,
|
||||
"value": 1.0
|
||||
},
|
||||
{
|
||||
"name": "core:CountryCodeState",
|
||||
"type": 3,
|
||||
"value": "TH"
|
||||
},
|
||||
{
|
||||
"name": "core:LocalIPv4AddressState",
|
||||
"type": 3,
|
||||
"value": "N/A"
|
||||
}
|
||||
],
|
||||
"available": true,
|
||||
"enabled": true,
|
||||
"placeOID": "6133b4a0-f514-4553-b635-d1b7beb7e7b2",
|
||||
"widget": "Pod",
|
||||
"type": 1,
|
||||
"oid": "2dfeb3c8-a71d-4552-9e9b-875baf906a6c",
|
||||
"uiClass": "Pod"
|
||||
},
|
||||
{
|
||||
"creationTime": 1613676516000,
|
||||
"lastUpdateTime": 1613676516000,
|
||||
"label": "Patio Shutter",
|
||||
"deviceURL": "rts://1234-1234-6362/16730022",
|
||||
"shortcut": false,
|
||||
"controllableName": "rts:RollerShutterRTSComponent",
|
||||
"definition": {
|
||||
"commands": [
|
||||
{
|
||||
"commandName": "close",
|
||||
"nparams": 1
|
||||
},
|
||||
{
|
||||
"commandName": "down",
|
||||
"nparams": 1
|
||||
},
|
||||
{
|
||||
"commandName": "identify",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"commandName": "my",
|
||||
"nparams": 1
|
||||
},
|
||||
{
|
||||
"commandName": "open",
|
||||
"nparams": 1
|
||||
},
|
||||
{
|
||||
"commandName": "rest",
|
||||
"nparams": 1
|
||||
},
|
||||
{
|
||||
"commandName": "stop",
|
||||
"nparams": 1
|
||||
},
|
||||
{
|
||||
"commandName": "test",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"commandName": "up",
|
||||
"nparams": 1
|
||||
},
|
||||
{
|
||||
"commandName": "openConfiguration",
|
||||
"nparams": 1
|
||||
}
|
||||
],
|
||||
"states": [],
|
||||
"dataProperties": [
|
||||
{
|
||||
"value": "0",
|
||||
"qualifiedName": "core:identifyInterval"
|
||||
}
|
||||
],
|
||||
"widgetName": "UpDownRollerShutter",
|
||||
"uiProfiles": ["OpenCloseShutter", "OpenClose"],
|
||||
"uiClass": "RollerShutter",
|
||||
"qualifiedName": "rts:RollerShutterRTSComponent",
|
||||
"type": "ACTUATOR"
|
||||
},
|
||||
"attributes": [
|
||||
{
|
||||
"name": "rts:diy",
|
||||
"type": 6,
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"available": true,
|
||||
"enabled": true,
|
||||
"placeOID": "6133b4a0-f514-4553-b635-d1b7beb7e7b2",
|
||||
"widget": "UpDownRollerShutter",
|
||||
"type": 1,
|
||||
"oid": "d4da34c9-5cbf-4278-b8ec-ae66428b9522",
|
||||
"uiClass": "RollerShutter"
|
||||
},
|
||||
{
|
||||
"creationTime": 1613676640000,
|
||||
"lastUpdateTime": 1613676640000,
|
||||
"label": "Kitchen Shutter",
|
||||
"deviceURL": "rts://1234-1234-6362/16749917",
|
||||
"shortcut": false,
|
||||
"controllableName": "rts:RollerShutterRTSComponent",
|
||||
"definition": {
|
||||
"commands": [
|
||||
{
|
||||
"commandName": "close",
|
||||
"nparams": 1
|
||||
},
|
||||
{
|
||||
"commandName": "down",
|
||||
"nparams": 1
|
||||
},
|
||||
{
|
||||
"commandName": "identify",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"commandName": "my",
|
||||
"nparams": 1
|
||||
},
|
||||
{
|
||||
"commandName": "open",
|
||||
"nparams": 1
|
||||
},
|
||||
{
|
||||
"commandName": "rest",
|
||||
"nparams": 1
|
||||
},
|
||||
{
|
||||
"commandName": "stop",
|
||||
"nparams": 1
|
||||
},
|
||||
{
|
||||
"commandName": "test",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"commandName": "up",
|
||||
"nparams": 1
|
||||
},
|
||||
{
|
||||
"commandName": "openConfiguration",
|
||||
"nparams": 1
|
||||
}
|
||||
],
|
||||
"states": [],
|
||||
"dataProperties": [
|
||||
{
|
||||
"value": "0",
|
||||
"qualifiedName": "core:identifyInterval"
|
||||
}
|
||||
],
|
||||
"widgetName": "UpDownRollerShutter",
|
||||
"uiProfiles": ["OpenCloseShutter", "OpenClose"],
|
||||
"uiClass": "RollerShutter",
|
||||
"qualifiedName": "rts:RollerShutterRTSComponent",
|
||||
"type": "ACTUATOR"
|
||||
},
|
||||
"attributes": [
|
||||
{
|
||||
"name": "rts:diy",
|
||||
"type": 6,
|
||||
"value": false
|
||||
}
|
||||
],
|
||||
"available": true,
|
||||
"enabled": true,
|
||||
"placeOID": "6133b4a0-f514-4553-b635-d1b7beb7e7b2",
|
||||
"widget": "UpDownRollerShutter",
|
||||
"type": 1,
|
||||
"oid": "ef870fe7-daf3-4f33-b91e-62b2a809ef4e",
|
||||
"uiClass": "RollerShutter"
|
||||
}
|
||||
],
|
||||
"zones": [],
|
||||
"resellerDelegationType": "NEVER",
|
||||
"oid": "fee37cf6-1d39-49fc-8d67-af71dfe20c4d",
|
||||
"rootPlace": {
|
||||
"creationTime": 1613674982000,
|
||||
"lastUpdateTime": 1613674982000,
|
||||
"label": "Palm Court",
|
||||
"type": 0,
|
||||
"oid": "6133b4a0-f514-4553-b635-d1b7beb7e7b2",
|
||||
"subPlaces": []
|
||||
},
|
||||
"features": [
|
||||
{
|
||||
"name": "connexoon-rts-window",
|
||||
"source": "GATEWAY_TYPE"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,891 @@
|
||||
{
|
||||
"creationTime": 1665238624000,
|
||||
"lastUpdateTime": 1665238624000,
|
||||
"id": "SETUP-1234-5678-6867",
|
||||
"location": {
|
||||
"creationTime": 1665238624000,
|
||||
"lastUpdateTime": 1667054735000,
|
||||
"city": "**",
|
||||
"country": "**",
|
||||
"postalCode": "**",
|
||||
"addressLine1": "**",
|
||||
"addressLine2": "*",
|
||||
"timezone": "Europe/Amsterdam",
|
||||
"longitude": "**",
|
||||
"latitude": "**",
|
||||
"twilightMode": 2,
|
||||
"twilightAngle": "SOLAR",
|
||||
"twilightCity": "amsterdam",
|
||||
"summerSolsticeDuskMinutes": 1290,
|
||||
"winterSolsticeDuskMinutes": 990,
|
||||
"twilightOffsetEnabled": false,
|
||||
"dawnOffset": 0,
|
||||
"duskOffset": 0,
|
||||
"countryCode": "NL"
|
||||
},
|
||||
"gateways": [
|
||||
{
|
||||
"gatewayId": "1234-5678-6867",
|
||||
"type": 98,
|
||||
"subType": 1,
|
||||
"placeOID": "41d63e43-bfa8-4e24-8c16-4faae0448cab",
|
||||
"autoUpdateEnabled": true,
|
||||
"alive": true,
|
||||
"timeReliable": true,
|
||||
"connectivity": {
|
||||
"status": "OK",
|
||||
"protocolVersion": "2023.4.4"
|
||||
},
|
||||
"upToDate": true,
|
||||
"updateStatus": "UP_TO_DATE",
|
||||
"syncInProgress": false,
|
||||
"mode": "ACTIVE",
|
||||
"functions": "INTERNET_AUTHORIZATION,SCENARIO_DOWNLOAD,SCENARIO_AUTO_LAUNCHING,SCENARIO_TELECO_LAUNCHING,INTERNET_UPLOAD,INTERNET_UPDATE,TRIGGERS_SENSORS"
|
||||
}
|
||||
],
|
||||
"devices": [
|
||||
{
|
||||
"creationTime": 1665238630000,
|
||||
"lastUpdateTime": 1665238630000,
|
||||
"label": "Study Protocol Gateway",
|
||||
"deviceURL": "homekit://1234-5678-6867/stack",
|
||||
"shortcut": false,
|
||||
"controllableName": "homekit:StackComponent",
|
||||
"definition": {
|
||||
"commands": [
|
||||
{
|
||||
"commandName": "deleteControllers",
|
||||
"nparams": 0
|
||||
}
|
||||
],
|
||||
"states": [],
|
||||
"dataProperties": [],
|
||||
"widgetName": "HomekitStack",
|
||||
"uiProfiles": ["Specific"],
|
||||
"uiClass": "ProtocolGateway",
|
||||
"qualifiedName": "homekit:StackComponent",
|
||||
"type": "PROTOCOL_GATEWAY"
|
||||
},
|
||||
"attributes": [
|
||||
{
|
||||
"name": "homekit:SetupPayload",
|
||||
"type": 3,
|
||||
"value": "X-HM://0024YABC1234"
|
||||
},
|
||||
{
|
||||
"name": "homekit:SetupCode",
|
||||
"type": 3,
|
||||
"value": "012-34-567"
|
||||
}
|
||||
],
|
||||
"available": true,
|
||||
"enabled": true,
|
||||
"placeOID": "41d63e43-bfa8-4e24-8c16-4faae0448cab",
|
||||
"type": 5,
|
||||
"widget": "HomekitStack",
|
||||
"oid": "ab964849-56ca-4e9c-a58c-33ce5e341b68",
|
||||
"uiClass": "ProtocolGateway"
|
||||
},
|
||||
{
|
||||
"creationTime": 1665238630000,
|
||||
"lastUpdateTime": 1665238630000,
|
||||
"label": "Nursery Hub",
|
||||
"deviceURL": "internal://1234-5678-6867/pod/0",
|
||||
"shortcut": false,
|
||||
"controllableName": "internal:PodV3Component",
|
||||
"definition": {
|
||||
"commands": [
|
||||
{
|
||||
"commandName": "getName",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"commandName": "update",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"commandName": "setCountryCode",
|
||||
"nparams": 1
|
||||
},
|
||||
{
|
||||
"commandName": "activateCalendar",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"commandName": "deactivateCalendar",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"commandName": "refreshPodMode",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"commandName": "refreshUpdateStatus",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"commandName": "setCalendar",
|
||||
"nparams": 1
|
||||
},
|
||||
{
|
||||
"commandName": "setLightingLedPodMode",
|
||||
"nparams": 1
|
||||
},
|
||||
{
|
||||
"commandName": "setPodLedOff",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"commandName": "setPodLedOn",
|
||||
"nparams": 0
|
||||
}
|
||||
],
|
||||
"states": [
|
||||
{
|
||||
"type": "DiscreteState",
|
||||
"values": ["offline", "online"],
|
||||
"qualifiedName": "core:ConnectivityState"
|
||||
},
|
||||
{
|
||||
"type": "DataState",
|
||||
"qualifiedName": "core:CountryCodeState"
|
||||
},
|
||||
{
|
||||
"eventBased": true,
|
||||
"type": "DataState",
|
||||
"qualifiedName": "core:LocalAccessProofState"
|
||||
},
|
||||
{
|
||||
"type": "DataState",
|
||||
"qualifiedName": "core:LocalIPv4AddressState"
|
||||
},
|
||||
{
|
||||
"type": "DataState",
|
||||
"qualifiedName": "core:NameState"
|
||||
},
|
||||
{
|
||||
"eventBased": true,
|
||||
"type": "DiscreteState",
|
||||
"values": ["pressed", "stop"],
|
||||
"qualifiedName": "internal:Button1State"
|
||||
},
|
||||
{
|
||||
"eventBased": true,
|
||||
"type": "DiscreteState",
|
||||
"values": ["pressed", "stop"],
|
||||
"qualifiedName": "internal:Button2State"
|
||||
},
|
||||
{
|
||||
"eventBased": true,
|
||||
"type": "DiscreteState",
|
||||
"values": ["pressed", "stop"],
|
||||
"qualifiedName": "internal:Button3State"
|
||||
},
|
||||
{
|
||||
"type": "ContinuousState",
|
||||
"qualifiedName": "internal:LightingLedPodModeState"
|
||||
}
|
||||
],
|
||||
"dataProperties": [],
|
||||
"widgetName": "Pod",
|
||||
"uiProfiles": ["UpdatableComponent"],
|
||||
"uiClass": "Pod",
|
||||
"qualifiedName": "internal:PodV3Component",
|
||||
"type": "ACTUATOR"
|
||||
},
|
||||
"states": [
|
||||
{
|
||||
"name": "internal:LightingLedPodModeState",
|
||||
"type": 2,
|
||||
"value": 1
|
||||
},
|
||||
{
|
||||
"name": "core:CountryCodeState",
|
||||
"type": 3,
|
||||
"value": "NL"
|
||||
},
|
||||
{
|
||||
"name": "internal:Button1State",
|
||||
"type": 3,
|
||||
"value": "pressed"
|
||||
},
|
||||
{
|
||||
"name": "internal:Button3State",
|
||||
"type": 3,
|
||||
"value": "stop"
|
||||
},
|
||||
{
|
||||
"name": "core:LocalAccessProofState",
|
||||
"type": 3,
|
||||
"value": "localAccessProof"
|
||||
},
|
||||
{
|
||||
"name": "core:LocalIPv4AddressState",
|
||||
"type": 3,
|
||||
"value": "192.168.1.42"
|
||||
},
|
||||
{
|
||||
"name": "core:NameState",
|
||||
"type": 3,
|
||||
"value": "Nursery Hub"
|
||||
}
|
||||
],
|
||||
"available": true,
|
||||
"enabled": true,
|
||||
"placeOID": "41d63e43-bfa8-4e24-8c16-4faae0448cab",
|
||||
"type": 1,
|
||||
"widget": "Pod",
|
||||
"oid": "c79a8bf6-59d6-434e-8cfd-97193541fa17",
|
||||
"uiClass": "Pod"
|
||||
},
|
||||
{
|
||||
"creationTime": 1665238630000,
|
||||
"lastUpdateTime": 1665238630000,
|
||||
"label": "Terrace Wifi",
|
||||
"deviceURL": "internal://1234-5678-6867/wifi/0",
|
||||
"shortcut": false,
|
||||
"controllableName": "internal:WifiComponent",
|
||||
"definition": {
|
||||
"commands": [
|
||||
{
|
||||
"commandName": "clearCredentials",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"commandName": "setTargetInfraConfig",
|
||||
"nparams": 2
|
||||
},
|
||||
{
|
||||
"commandName": "setWifiMode",
|
||||
"nparams": 1
|
||||
}
|
||||
],
|
||||
"states": [
|
||||
{
|
||||
"type": "DataState",
|
||||
"qualifiedName": "internal:CurrentInfraConfigState"
|
||||
},
|
||||
{
|
||||
"type": "ContinuousState",
|
||||
"qualifiedName": "internal:SignalStrengthState"
|
||||
},
|
||||
{
|
||||
"type": "DataState",
|
||||
"qualifiedName": "internal:WifiModeState"
|
||||
}
|
||||
],
|
||||
"dataProperties": [],
|
||||
"widgetName": "Wifi",
|
||||
"uiProfiles": ["Specific"],
|
||||
"uiClass": "Wifi",
|
||||
"qualifiedName": "internal:WifiComponent",
|
||||
"type": "ACTUATOR"
|
||||
},
|
||||
"states": [
|
||||
{
|
||||
"name": "internal:WifiModeState",
|
||||
"type": 3,
|
||||
"value": "infrastructure"
|
||||
},
|
||||
{
|
||||
"name": "internal:CurrentInfraConfigState",
|
||||
"type": 3,
|
||||
"value": "AM"
|
||||
},
|
||||
{
|
||||
"name": "internal:SignalStrengthState",
|
||||
"type": 1,
|
||||
"value": 69
|
||||
}
|
||||
],
|
||||
"available": true,
|
||||
"enabled": true,
|
||||
"placeOID": "41d63e43-bfa8-4e24-8c16-4faae0448cab",
|
||||
"type": 1,
|
||||
"widget": "Wifi",
|
||||
"oid": "4272c61b-5493-453c-8d87-a58e45ef60f8",
|
||||
"uiClass": "Wifi"
|
||||
},
|
||||
{
|
||||
"creationTime": 1665238924000,
|
||||
"lastUpdateTime": 1665238924000,
|
||||
"label": "Bathroom Bridge",
|
||||
"deviceURL": "io://1234-5678-6867/4167385",
|
||||
"shortcut": false,
|
||||
"controllableName": "io:StackComponent",
|
||||
"definition": {
|
||||
"commands": [
|
||||
{
|
||||
"commandName": "advancedSomfyDiscover",
|
||||
"nparams": 1
|
||||
},
|
||||
{
|
||||
"commandName": "discover1WayController",
|
||||
"nparams": 2
|
||||
},
|
||||
{
|
||||
"commandName": "discoverActuators",
|
||||
"nparams": 1
|
||||
},
|
||||
{
|
||||
"commandName": "discoverSensors",
|
||||
"nparams": 1
|
||||
},
|
||||
{
|
||||
"commandName": "discoverSomfyUnsetActuators",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"commandName": "joinNetwork",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"commandName": "resetNetworkSecurity",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"commandName": "shareNetwork",
|
||||
"nparams": 0
|
||||
}
|
||||
],
|
||||
"states": [],
|
||||
"dataProperties": [],
|
||||
"widgetName": "IOStack",
|
||||
"uiProfiles": ["Specific"],
|
||||
"uiClass": "ProtocolGateway",
|
||||
"qualifiedName": "io:StackComponent",
|
||||
"type": "PROTOCOL_GATEWAY"
|
||||
},
|
||||
"available": true,
|
||||
"enabled": true,
|
||||
"placeOID": "41d63e43-bfa8-4e24-8c16-4faae0448cab",
|
||||
"type": 5,
|
||||
"widget": "IOStack",
|
||||
"oid": "bb301e56-0957-417f-ba37-26efc11659aa",
|
||||
"uiClass": "ProtocolGateway"
|
||||
},
|
||||
{
|
||||
"creationTime": 1665238637000,
|
||||
"lastUpdateTime": 1665238637000,
|
||||
"label": "Garage Protocol Gateway",
|
||||
"deviceURL": "ogp://1234-5678-6867/00000BE8",
|
||||
"shortcut": false,
|
||||
"controllableName": "ogp:Bridge",
|
||||
"definition": {
|
||||
"commands": [
|
||||
{
|
||||
"commandName": "identify",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"commandName": "sendPrivate",
|
||||
"nparams": 1
|
||||
},
|
||||
{
|
||||
"commandName": "setName",
|
||||
"nparams": 1
|
||||
}
|
||||
],
|
||||
"states": [
|
||||
{
|
||||
"type": "DiscreteState",
|
||||
"values": ["available", "unavailable"],
|
||||
"qualifiedName": "core:AvailabilityState"
|
||||
},
|
||||
{
|
||||
"type": "DataState",
|
||||
"qualifiedName": "core:NameState"
|
||||
},
|
||||
{
|
||||
"type": "DataState",
|
||||
"qualifiedName": "core:Private10State"
|
||||
},
|
||||
{
|
||||
"type": "DataState",
|
||||
"qualifiedName": "core:Private1State"
|
||||
},
|
||||
{
|
||||
"type": "DataState",
|
||||
"qualifiedName": "core:Private2State"
|
||||
},
|
||||
{
|
||||
"type": "DataState",
|
||||
"qualifiedName": "core:Private3State"
|
||||
},
|
||||
{
|
||||
"type": "DataState",
|
||||
"qualifiedName": "core:Private4State"
|
||||
},
|
||||
{
|
||||
"type": "DataState",
|
||||
"qualifiedName": "core:Private5State"
|
||||
},
|
||||
{
|
||||
"type": "DataState",
|
||||
"qualifiedName": "core:Private6State"
|
||||
},
|
||||
{
|
||||
"type": "DataState",
|
||||
"qualifiedName": "core:Private7State"
|
||||
},
|
||||
{
|
||||
"type": "DataState",
|
||||
"qualifiedName": "core:Private8State"
|
||||
},
|
||||
{
|
||||
"type": "DataState",
|
||||
"qualifiedName": "core:Private9State"
|
||||
},
|
||||
{
|
||||
"type": "DataState",
|
||||
"qualifiedName": "core:RemovableState"
|
||||
}
|
||||
],
|
||||
"dataProperties": [],
|
||||
"widgetName": "DynamicBridge",
|
||||
"uiProfiles": ["Specific"],
|
||||
"uiClass": "ProtocolGateway",
|
||||
"qualifiedName": "ogp:Bridge",
|
||||
"type": "ACTUATOR"
|
||||
},
|
||||
"states": [
|
||||
{
|
||||
"name": "core:NameState",
|
||||
"type": 3,
|
||||
"value": "Garage Protocol Gateway"
|
||||
}
|
||||
],
|
||||
"attributes": [
|
||||
{
|
||||
"name": "core:Technology",
|
||||
"type": 3,
|
||||
"value": "KNX"
|
||||
},
|
||||
{
|
||||
"name": "core:ManufacturerReference",
|
||||
"type": 3,
|
||||
"value": "OGP KNX Bridge"
|
||||
},
|
||||
{
|
||||
"name": "ogp:Features",
|
||||
"type": 10,
|
||||
"value": [
|
||||
{
|
||||
"name": "private"
|
||||
},
|
||||
{
|
||||
"name": "identification"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "core:Manufacturer",
|
||||
"type": 3,
|
||||
"value": "Overkiz"
|
||||
}
|
||||
],
|
||||
"available": true,
|
||||
"enabled": true,
|
||||
"placeOID": "41d63e43-bfa8-4e24-8c16-4faae0448cab",
|
||||
"type": 1,
|
||||
"widget": "DynamicBridge",
|
||||
"oid": "e88717c3-02a9-49b6-a5a5-5adca558afe9",
|
||||
"uiClass": "ProtocolGateway"
|
||||
},
|
||||
{
|
||||
"creationTime": 1665238799000,
|
||||
"lastUpdateTime": 1665238799000,
|
||||
"label": "Dining Room Protocol Gateway",
|
||||
"deviceURL": "ogp://1234-5678-6867/0003FEF3",
|
||||
"shortcut": false,
|
||||
"controllableName": "ogp:Bridge",
|
||||
"definition": {
|
||||
"commands": [
|
||||
{
|
||||
"commandName": "discover",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"commandName": "reset",
|
||||
"nparams": 0
|
||||
}
|
||||
],
|
||||
"states": [
|
||||
{
|
||||
"type": "DiscreteState",
|
||||
"values": ["available", "unavailable"],
|
||||
"qualifiedName": "core:AvailabilityState"
|
||||
},
|
||||
{
|
||||
"type": "DataState",
|
||||
"qualifiedName": "core:NameState"
|
||||
},
|
||||
{
|
||||
"type": "DataState",
|
||||
"qualifiedName": "core:RemovableState"
|
||||
}
|
||||
],
|
||||
"dataProperties": [],
|
||||
"widgetName": "DynamicBridge",
|
||||
"uiProfiles": ["Specific"],
|
||||
"uiClass": "ProtocolGateway",
|
||||
"qualifiedName": "ogp:Bridge",
|
||||
"type": "ACTUATOR"
|
||||
},
|
||||
"states": [
|
||||
{
|
||||
"name": "core:NameState",
|
||||
"type": 3,
|
||||
"value": "Dining Room Protocol Gateway"
|
||||
}
|
||||
],
|
||||
"attributes": [
|
||||
{
|
||||
"name": "core:ManufacturerReference",
|
||||
"type": 3,
|
||||
"value": "OGP Sonos Bridge"
|
||||
},
|
||||
{
|
||||
"name": "core:Manufacturer",
|
||||
"type": 3,
|
||||
"value": "Overkiz"
|
||||
},
|
||||
{
|
||||
"name": "ogp:Features",
|
||||
"type": 10,
|
||||
"value": [
|
||||
{
|
||||
"name": "identification",
|
||||
"commandLess": true
|
||||
},
|
||||
{
|
||||
"name": "discovery"
|
||||
},
|
||||
{
|
||||
"name": "reset"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "core:Technology",
|
||||
"type": 3,
|
||||
"value": "Sonos"
|
||||
}
|
||||
],
|
||||
"available": true,
|
||||
"enabled": true,
|
||||
"placeOID": "41d63e43-bfa8-4e24-8c16-4faae0448cab",
|
||||
"type": 1,
|
||||
"widget": "DynamicBridge",
|
||||
"oid": "4031915f-df40-4a70-a97f-64031182a507",
|
||||
"uiClass": "ProtocolGateway"
|
||||
},
|
||||
{
|
||||
"creationTime": 1665238637000,
|
||||
"lastUpdateTime": 1665238637000,
|
||||
"label": "Living Room Bridge",
|
||||
"deviceURL": "ogp://1234-5678-6867/039575E9",
|
||||
"shortcut": false,
|
||||
"controllableName": "ogp:Bridge",
|
||||
"definition": {
|
||||
"commands": [
|
||||
{
|
||||
"commandName": "discover",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"commandName": "identify",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"commandName": "setName",
|
||||
"nparams": 1
|
||||
}
|
||||
],
|
||||
"states": [
|
||||
{
|
||||
"type": "DiscreteState",
|
||||
"values": ["available", "unavailable"],
|
||||
"qualifiedName": "core:AvailabilityState"
|
||||
},
|
||||
{
|
||||
"type": "DataState",
|
||||
"qualifiedName": "core:NameState"
|
||||
},
|
||||
{
|
||||
"type": "DataState",
|
||||
"qualifiedName": "core:RemovableState"
|
||||
}
|
||||
],
|
||||
"dataProperties": [],
|
||||
"widgetName": "DynamicBridge",
|
||||
"uiProfiles": ["Specific"],
|
||||
"uiClass": "ProtocolGateway",
|
||||
"qualifiedName": "ogp:Bridge",
|
||||
"type": "ACTUATOR"
|
||||
},
|
||||
"states": [
|
||||
{
|
||||
"name": "core:NameState",
|
||||
"type": 3,
|
||||
"value": "Living Room Bridge"
|
||||
}
|
||||
],
|
||||
"attributes": [
|
||||
{
|
||||
"name": "core:Manufacturer",
|
||||
"type": 3,
|
||||
"value": "Overkiz"
|
||||
},
|
||||
{
|
||||
"name": "ogp:Features",
|
||||
"type": 10,
|
||||
"value": [
|
||||
{
|
||||
"name": "discovery"
|
||||
},
|
||||
{
|
||||
"name": "identification"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "core:ManufacturerReference",
|
||||
"type": 3,
|
||||
"value": "OGP Siegenia Bridge"
|
||||
},
|
||||
{
|
||||
"name": "core:Technology",
|
||||
"type": 3,
|
||||
"value": "Siegenia"
|
||||
}
|
||||
],
|
||||
"available": true,
|
||||
"enabled": true,
|
||||
"placeOID": "41d63e43-bfa8-4e24-8c16-4faae0448cab",
|
||||
"type": 1,
|
||||
"widget": "DynamicBridge",
|
||||
"oid": "5cdf0023-2d7e-4e8e-bfb0-74ebb6ebe0eb",
|
||||
"uiClass": "ProtocolGateway"
|
||||
},
|
||||
{
|
||||
"creationTime": 1665238637000,
|
||||
"lastUpdateTime": 1665238637000,
|
||||
"label": "Patio Protocol Gateway",
|
||||
"deviceURL": "ogp://1234-5678-6867/09E45393",
|
||||
"shortcut": false,
|
||||
"controllableName": "ogp:Bridge",
|
||||
"definition": {
|
||||
"commands": [
|
||||
{
|
||||
"commandName": "discover",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"commandName": "identify",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"commandName": "setName",
|
||||
"nparams": 1
|
||||
}
|
||||
],
|
||||
"states": [
|
||||
{
|
||||
"type": "DiscreteState",
|
||||
"values": ["available", "unavailable"],
|
||||
"qualifiedName": "core:AvailabilityState"
|
||||
},
|
||||
{
|
||||
"type": "DataState",
|
||||
"qualifiedName": "core:NameState"
|
||||
},
|
||||
{
|
||||
"type": "DataState",
|
||||
"qualifiedName": "core:RemovableState"
|
||||
}
|
||||
],
|
||||
"dataProperties": [],
|
||||
"widgetName": "DynamicBridge",
|
||||
"uiProfiles": ["Specific"],
|
||||
"uiClass": "ProtocolGateway",
|
||||
"qualifiedName": "ogp:Bridge",
|
||||
"type": "ACTUATOR"
|
||||
},
|
||||
"states": [
|
||||
{
|
||||
"name": "core:NameState",
|
||||
"type": 3,
|
||||
"value": "Patio Protocol Gateway"
|
||||
}
|
||||
],
|
||||
"attributes": [
|
||||
{
|
||||
"name": "core:ManufacturerReference",
|
||||
"type": 3,
|
||||
"value": "OGP Intesis Bridge"
|
||||
},
|
||||
{
|
||||
"name": "ogp:Features",
|
||||
"type": 10,
|
||||
"value": [
|
||||
{
|
||||
"name": "discovery"
|
||||
},
|
||||
{
|
||||
"name": "identification"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "core:Manufacturer",
|
||||
"type": 3,
|
||||
"value": "Overkiz"
|
||||
},
|
||||
{
|
||||
"name": "core:Technology",
|
||||
"type": 3,
|
||||
"value": "Intesis"
|
||||
}
|
||||
],
|
||||
"available": true,
|
||||
"enabled": true,
|
||||
"placeOID": "41d63e43-bfa8-4e24-8c16-4faae0448cab",
|
||||
"type": 1,
|
||||
"widget": "DynamicBridge",
|
||||
"oid": "b1f5dc24-058e-4cb2-a052-7b2d5a7de7a5",
|
||||
"uiClass": "ProtocolGateway"
|
||||
},
|
||||
{
|
||||
"creationTime": 1667840384000,
|
||||
"lastUpdateTime": 1667840384000,
|
||||
"label": "Living Room Shutter",
|
||||
"deviceURL": "rts://1234-5678-6867/16756006",
|
||||
"shortcut": false,
|
||||
"controllableName": "rts:RollerShutterRTSComponent",
|
||||
"definition": {
|
||||
"commands": [
|
||||
{
|
||||
"commandName": "close",
|
||||
"nparams": 1
|
||||
},
|
||||
{
|
||||
"commandName": "down",
|
||||
"nparams": 1
|
||||
},
|
||||
{
|
||||
"commandName": "identify",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"commandName": "my",
|
||||
"nparams": 1
|
||||
},
|
||||
{
|
||||
"commandName": "open",
|
||||
"nparams": 1
|
||||
},
|
||||
{
|
||||
"commandName": "rest",
|
||||
"nparams": 1
|
||||
},
|
||||
{
|
||||
"commandName": "stop",
|
||||
"nparams": 1
|
||||
},
|
||||
{
|
||||
"commandName": "test",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"commandName": "up",
|
||||
"nparams": 1
|
||||
},
|
||||
{
|
||||
"commandName": "openConfiguration",
|
||||
"nparams": 1
|
||||
}
|
||||
],
|
||||
"states": [],
|
||||
"dataProperties": [
|
||||
{
|
||||
"value": "0",
|
||||
"qualifiedName": "core:identifyInterval"
|
||||
}
|
||||
],
|
||||
"widgetName": "UpDownRollerShutter",
|
||||
"uiProfiles": ["OpenCloseShutter", "OpenClose"],
|
||||
"uiClass": "RollerShutter",
|
||||
"qualifiedName": "rts:RollerShutterRTSComponent",
|
||||
"type": "ACTUATOR"
|
||||
},
|
||||
"attributes": [
|
||||
{
|
||||
"name": "rts:diy",
|
||||
"type": 6,
|
||||
"value": true
|
||||
}
|
||||
],
|
||||
"available": true,
|
||||
"enabled": true,
|
||||
"placeOID": "9e3d6899-50bb-4869-9c5e-46c2b57f7c9e",
|
||||
"type": 1,
|
||||
"widget": "UpDownRollerShutter",
|
||||
"oid": "1a10d6f6-9bc3-40f3-a33c-e383fd41d3e8",
|
||||
"uiClass": "RollerShutter"
|
||||
},
|
||||
{
|
||||
"creationTime": 1665238630000,
|
||||
"lastUpdateTime": 1665238630000,
|
||||
"label": "Attic Side Bridge",
|
||||
"deviceURL": "zigbee://1234-5678-6867/65535",
|
||||
"shortcut": false,
|
||||
"controllableName": "zigbee:TransceiverV3_0Component",
|
||||
"definition": {
|
||||
"commands": [],
|
||||
"states": [],
|
||||
"dataProperties": [],
|
||||
"widgetName": "ZigbeeStack",
|
||||
"uiProfiles": ["Specific"],
|
||||
"uiClass": "ProtocolGateway",
|
||||
"qualifiedName": "zigbee:TransceiverV3_0Component",
|
||||
"type": "PROTOCOL_GATEWAY"
|
||||
},
|
||||
"available": true,
|
||||
"enabled": true,
|
||||
"placeOID": "41d63e43-bfa8-4e24-8c16-4faae0448cab",
|
||||
"type": 5,
|
||||
"widget": "ZigbeeStack",
|
||||
"oid": "1629c223-d115-4aad-808a-373f428d9c27",
|
||||
"uiClass": "ProtocolGateway"
|
||||
}
|
||||
],
|
||||
"zones": [],
|
||||
"resellerDelegationType": "NEVER",
|
||||
"disconnectionConfiguration": {
|
||||
"notificationTitle": "[User] : Your Somfy box is disconnected",
|
||||
"notificationText": "Your Somfy box is disconnected",
|
||||
"targetPushSubscriptions": ["8849df9a-b61a-498f-ab81-67a767adba31"],
|
||||
"notificationType": "PUSH"
|
||||
},
|
||||
"oid": "15eaf55a-8af9-483b-ae4a-ffd4254fd762",
|
||||
"rootPlace": {
|
||||
"creationTime": 1665238624000,
|
||||
"lastUpdateTime": 1665238630000,
|
||||
"label": "My House",
|
||||
"type": 200,
|
||||
"oid": "41d63e43-bfa8-4e24-8c16-4faae0448cab",
|
||||
"subPlaces": [
|
||||
{
|
||||
"creationTime": 1667840432000,
|
||||
"lastUpdateTime": 1667840432000,
|
||||
"label": "Living Room",
|
||||
"type": 108,
|
||||
"metadata": "{\"color\":\"#08C27F\"}",
|
||||
"oid": "9e3d6899-50bb-4869-9c5e-46c2b57f7c9e",
|
||||
"subPlaces": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"features": []
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,441 @@
|
||||
{
|
||||
"gateways": [
|
||||
{
|
||||
"connectivity": {
|
||||
"status": "OK",
|
||||
"protocolVersion": "2021.2.4-17"
|
||||
},
|
||||
"gatewayId": "1234-1234-1234"
|
||||
}
|
||||
],
|
||||
"devices": [
|
||||
{
|
||||
"deviceURL": "internal://1234-1234-1234/pod/0",
|
||||
"available": true,
|
||||
"synced": true,
|
||||
"type": 1,
|
||||
"states": [
|
||||
{
|
||||
"type": 3,
|
||||
"name": "core:CountryCodeState",
|
||||
"value": "NL"
|
||||
},
|
||||
{
|
||||
"type": 1,
|
||||
"name": "internal:LightingLedPodModeState",
|
||||
"value": 1
|
||||
},
|
||||
{
|
||||
"type": 3,
|
||||
"name": "core:NameState",
|
||||
"value": "*"
|
||||
},
|
||||
{
|
||||
"type": 3,
|
||||
"name": "core:ConnectivityState",
|
||||
"value": "online"
|
||||
},
|
||||
{
|
||||
"type": 3,
|
||||
"name": "core:LocalIPv4AddressState",
|
||||
"value": "192.168.150.8"
|
||||
}
|
||||
],
|
||||
"label": "*",
|
||||
"subsystemId": 0,
|
||||
"attributes": [],
|
||||
"enabled": true,
|
||||
"controllableName": "internal:PodMiniComponent",
|
||||
"definition": {
|
||||
"states": [
|
||||
{
|
||||
"name": "core:ConnectivityState"
|
||||
},
|
||||
{
|
||||
"name": "core:CountryCodeState"
|
||||
},
|
||||
{
|
||||
"name": "core:LocalIPv4AddressState"
|
||||
},
|
||||
{
|
||||
"name": "core:NameState"
|
||||
},
|
||||
{
|
||||
"name": "internal:LastActionConfigButtonState"
|
||||
},
|
||||
{
|
||||
"name": "internal:LightingLedPodModeState"
|
||||
}
|
||||
],
|
||||
"widgetName": "Pod",
|
||||
"type": "ACTUATOR",
|
||||
"commands": [
|
||||
{
|
||||
"commandName": "activateCalendar",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"commandName": "deactivateCalendar",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"commandName": "getName",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"commandName": "refreshPodMode",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"commandName": "refreshUpdateStatus",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"nparams": 1,
|
||||
"commandName": "setCalendar",
|
||||
"paramsSig": "p1"
|
||||
},
|
||||
{
|
||||
"nparams": 1,
|
||||
"commandName": "setCountryCode",
|
||||
"paramsSig": "p1"
|
||||
},
|
||||
{
|
||||
"nparams": 1,
|
||||
"commandName": "setLightingLedPodMode",
|
||||
"paramsSig": "p1"
|
||||
},
|
||||
{
|
||||
"commandName": "setPodLedOff",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"commandName": "setPodLedOn",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"commandName": "update",
|
||||
"nparams": 0
|
||||
}
|
||||
],
|
||||
"uiClass": "Pod"
|
||||
}
|
||||
},
|
||||
{
|
||||
"deviceURL": "io://1234-1234-1234/5928357",
|
||||
"available": true,
|
||||
"synced": true,
|
||||
"type": 1,
|
||||
"states": [
|
||||
{
|
||||
"type": 3,
|
||||
"name": "core:StatusState",
|
||||
"value": "available"
|
||||
},
|
||||
{
|
||||
"type": 3,
|
||||
"name": "core:DiscreteRSSILevelState",
|
||||
"value": "good"
|
||||
},
|
||||
{
|
||||
"type": 1,
|
||||
"name": "core:RSSILevelState",
|
||||
"value": 88
|
||||
},
|
||||
{
|
||||
"type": 1,
|
||||
"name": "core:DeploymentState",
|
||||
"value": 0
|
||||
},
|
||||
{
|
||||
"type": 11,
|
||||
"name": "core:ManufacturerSettingsState",
|
||||
"value": {
|
||||
"currentPosition": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": 3,
|
||||
"name": "core:OpenClosedState",
|
||||
"value": "closed"
|
||||
},
|
||||
{
|
||||
"type": 1,
|
||||
"name": "core:TargetClosureState",
|
||||
"value": 0
|
||||
},
|
||||
{
|
||||
"type": 6,
|
||||
"name": "core:MovingState",
|
||||
"value": false
|
||||
},
|
||||
{
|
||||
"type": 3,
|
||||
"name": "core:NameState",
|
||||
"value": "Terrace Awning"
|
||||
},
|
||||
{
|
||||
"type": 1,
|
||||
"name": "core:Memorized1PositionState",
|
||||
"value": 105
|
||||
}
|
||||
],
|
||||
"label": "Terrace Awning",
|
||||
"subsystemId": 0,
|
||||
"attributes": [
|
||||
{
|
||||
"type": 3,
|
||||
"name": "core:Manufacturer",
|
||||
"value": "Somfy"
|
||||
},
|
||||
{
|
||||
"type": 3,
|
||||
"name": "core:FirmwareRevision",
|
||||
"value": "5071665X10\u0003"
|
||||
}
|
||||
],
|
||||
"enabled": true,
|
||||
"controllableName": "io:HorizontalAwningIOComponent",
|
||||
"definition": {
|
||||
"states": [
|
||||
{
|
||||
"name": "core:AdditionalStatusState"
|
||||
},
|
||||
{
|
||||
"name": "core:DeploymentState"
|
||||
},
|
||||
{
|
||||
"name": "core:DiscreteRSSILevelState"
|
||||
},
|
||||
{
|
||||
"name": "core:ManufacturerSettingsState"
|
||||
},
|
||||
{
|
||||
"name": "core:Memorized1PositionState"
|
||||
},
|
||||
{
|
||||
"name": "core:MovingState"
|
||||
},
|
||||
{
|
||||
"name": "core:NameState"
|
||||
},
|
||||
{
|
||||
"name": "core:OpenClosedState"
|
||||
},
|
||||
{
|
||||
"name": "core:RSSILevelState"
|
||||
},
|
||||
{
|
||||
"name": "core:SecuredPositionState"
|
||||
},
|
||||
{
|
||||
"name": "core:StatusState"
|
||||
},
|
||||
{
|
||||
"name": "core:TargetClosureState"
|
||||
}
|
||||
],
|
||||
"widgetName": "PositionableHorizontalAwning",
|
||||
"type": "ACTUATOR",
|
||||
"commands": [
|
||||
{
|
||||
"nparams": 1,
|
||||
"commandName": "advancedRefresh",
|
||||
"paramsSig": "p1"
|
||||
},
|
||||
{
|
||||
"commandName": "close",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"nparams": 1,
|
||||
"commandName": "delayedStopIdentify",
|
||||
"paramsSig": "p1"
|
||||
},
|
||||
{
|
||||
"commandName": "deploy",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"commandName": "down",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"commandName": "getName",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"commandName": "identify",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"commandName": "keepOneWayControllersAndDeleteNode",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"commandName": "my",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"commandName": "open",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"nparams": 1,
|
||||
"commandName": "pairOneWayController",
|
||||
"paramsSig": "p1,*p2"
|
||||
},
|
||||
{
|
||||
"commandName": "refreshMemorized1Position",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"nparams": 2,
|
||||
"commandName": "runManufacturerSettingsCommand",
|
||||
"paramsSig": "p1,p2"
|
||||
},
|
||||
{
|
||||
"commandName": "sendIOKey",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"nparams": 1,
|
||||
"commandName": "setClosure",
|
||||
"paramsSig": "p1"
|
||||
},
|
||||
{
|
||||
"nparams": 1,
|
||||
"commandName": "setConfigState",
|
||||
"paramsSig": "p1"
|
||||
},
|
||||
{
|
||||
"nparams": 1,
|
||||
"commandName": "setDeployment",
|
||||
"paramsSig": "p1"
|
||||
},
|
||||
{
|
||||
"nparams": 1,
|
||||
"commandName": "setMemorized1Position",
|
||||
"paramsSig": "p1"
|
||||
},
|
||||
{
|
||||
"nparams": 1,
|
||||
"commandName": "setName",
|
||||
"paramsSig": "p1"
|
||||
},
|
||||
{
|
||||
"nparams": 1,
|
||||
"commandName": "setPosition",
|
||||
"paramsSig": "p1"
|
||||
},
|
||||
{
|
||||
"nparams": 1,
|
||||
"commandName": "setSecuredPosition",
|
||||
"paramsSig": "p1"
|
||||
},
|
||||
{
|
||||
"commandName": "startIdentify",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"commandName": "stop",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"commandName": "stopIdentify",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"commandName": "undeploy",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"commandName": "unpairAllOneWayControllers",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"commandName": "unpairAllOneWayControllersAndDeleteNode",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"nparams": 1,
|
||||
"commandName": "unpairOneWayController",
|
||||
"paramsSig": "p1,*p2"
|
||||
},
|
||||
{
|
||||
"commandName": "up",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"nparams": 1,
|
||||
"commandName": "wink",
|
||||
"paramsSig": "p1"
|
||||
}
|
||||
],
|
||||
"uiClass": "Awning"
|
||||
}
|
||||
},
|
||||
{
|
||||
"deviceURL": "io://1234-1234-1234/16516299",
|
||||
"available": true,
|
||||
"synced": true,
|
||||
"type": 5,
|
||||
"states": [],
|
||||
"label": "* (*)",
|
||||
"subsystemId": 0,
|
||||
"attributes": [
|
||||
{
|
||||
"type": 3,
|
||||
"name": "core:Manufacturer",
|
||||
"value": "Somfy"
|
||||
}
|
||||
],
|
||||
"enabled": true,
|
||||
"controllableName": "io:StackComponent",
|
||||
"definition": {
|
||||
"states": [],
|
||||
"widgetName": "IOStack",
|
||||
"type": "PROTOCOL_GATEWAY",
|
||||
"commands": [
|
||||
{
|
||||
"nparams": 1,
|
||||
"commandName": "advancedSomfyDiscover",
|
||||
"paramsSig": "p1"
|
||||
},
|
||||
{
|
||||
"nparams": 0,
|
||||
"commandName": "discover1WayController",
|
||||
"paramsSig": "*p1,*p2"
|
||||
},
|
||||
{
|
||||
"nparams": 1,
|
||||
"commandName": "discoverActuators",
|
||||
"paramsSig": "p1"
|
||||
},
|
||||
{
|
||||
"nparams": 1,
|
||||
"commandName": "discoverSensors",
|
||||
"paramsSig": "p1"
|
||||
},
|
||||
{
|
||||
"commandName": "discoverSomfyUnsetActuators",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"commandName": "joinNetwork",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"commandName": "resetNetworkSecurity",
|
||||
"nparams": 0
|
||||
},
|
||||
{
|
||||
"commandName": "shareNetwork",
|
||||
"nparams": 0
|
||||
}
|
||||
],
|
||||
"uiClass": "ProtocolGateway"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,64 @@
|
||||
"""Shared helpers for Overkiz integration tests."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import timedelta
|
||||
from typing import Any
|
||||
|
||||
from freezegun.api import FrozenDateTimeFactory
|
||||
from pyoverkiz.models import Event
|
||||
|
||||
from homeassistant.components.overkiz.const import UPDATE_INTERVAL
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from .conftest import MockOverkizClient
|
||||
|
||||
from tests.common import async_fire_time_changed
|
||||
|
||||
|
||||
def assert_command_call(
|
||||
mock_client: MockOverkizClient,
|
||||
*,
|
||||
device_url: str,
|
||||
command_name: str,
|
||||
parameters: list[Any] | None = None,
|
||||
) -> None:
|
||||
"""Assert the latest command sent through the mocked Overkiz client."""
|
||||
assert mock_client.execute_command.await_count == 1
|
||||
args = mock_client.execute_command.await_args.args
|
||||
assert args[0] == device_url
|
||||
assert args[1].name == command_name
|
||||
assert args[1].parameters == (parameters or [])
|
||||
assert args[2] == "Home Assistant"
|
||||
|
||||
|
||||
def build_event(
|
||||
name: str,
|
||||
*,
|
||||
device_url: str,
|
||||
device_states: list[dict[str, Any]] | None = None,
|
||||
exec_id: str | None = None,
|
||||
new_state: str | None = None,
|
||||
) -> Event:
|
||||
"""Create a pyoverkiz event object with a test-friendly interface."""
|
||||
return Event(
|
||||
name=name,
|
||||
device_url=device_url,
|
||||
device_states=device_states,
|
||||
exec_id=exec_id,
|
||||
new_state=new_state,
|
||||
)
|
||||
|
||||
|
||||
async def async_deliver_events(
|
||||
hass: HomeAssistant,
|
||||
freezer: FrozenDateTimeFactory,
|
||||
mock_client: MockOverkizClient,
|
||||
*event_batches: list[Event],
|
||||
update_interval: timedelta = UPDATE_INTERVAL,
|
||||
) -> None:
|
||||
"""Queue event batches and advance time to trigger a coordinator refresh."""
|
||||
mock_client.queue_events(*event_batches)
|
||||
freezer.tick(update_interval)
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,679 @@
|
||||
"""Tests for the Overkiz cover platform."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Generator
|
||||
from pathlib import Path
|
||||
from typing import Any, NamedTuple
|
||||
from unittest.mock import patch
|
||||
|
||||
from freezegun.api import FrozenDateTimeFactory
|
||||
from pyoverkiz.enums import EventName, ExecutionState, OverkizCommandParam, OverkizState
|
||||
import pytest
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
|
||||
from homeassistant.components.cover import (
|
||||
ATTR_CURRENT_POSITION,
|
||||
ATTR_CURRENT_TILT_POSITION,
|
||||
ATTR_POSITION,
|
||||
ATTR_TILT_POSITION,
|
||||
DOMAIN as COVER_DOMAIN,
|
||||
SERVICE_CLOSE_COVER,
|
||||
SERVICE_CLOSE_COVER_TILT,
|
||||
SERVICE_OPEN_COVER,
|
||||
SERVICE_OPEN_COVER_TILT,
|
||||
SERVICE_SET_COVER_POSITION,
|
||||
SERVICE_SET_COVER_TILT_POSITION,
|
||||
SERVICE_STOP_COVER,
|
||||
SERVICE_STOP_COVER_TILT,
|
||||
CoverEntityFeature,
|
||||
CoverState,
|
||||
)
|
||||
from homeassistant.const import ATTR_ENTITY_ID, STATE_UNAVAILABLE, Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
from .conftest import MockOverkizClient, SetupOverkizIntegration
|
||||
from .helpers import assert_command_call, async_deliver_events, build_event
|
||||
|
||||
from tests.common import snapshot_platform
|
||||
|
||||
|
||||
class FixtureDevice(NamedTuple):
|
||||
"""Test device binding a fixture file to a device URL and entity id."""
|
||||
|
||||
fixture: str
|
||||
device_url: str
|
||||
entity_id: str
|
||||
|
||||
|
||||
AWNING = FixtureDevice(
|
||||
"setup/local_somfy_connexoon_europe.json",
|
||||
"io://1234-1234-1234/5928357",
|
||||
"cover.terrace_awning",
|
||||
)
|
||||
LOW_SPEED = FixtureDevice(
|
||||
"setup/cloud_nexity_rail_din_europe.json",
|
||||
"io://1234-5678-1698/141613",
|
||||
"cover.nursery_shutter",
|
||||
)
|
||||
PERGOLA = FixtureDevice(
|
||||
"setup/local_somfy_tahoma_v2_europe.json",
|
||||
"io://1234-5678-3293/7614902",
|
||||
"cover.garden_pergola",
|
||||
)
|
||||
RTS = FixtureDevice(
|
||||
"setup/cloud_somfy_connexoon_rts_asia.json",
|
||||
"rts://1234-1234-6362/16730022",
|
||||
"cover.patio_shutter",
|
||||
)
|
||||
SHUTTER = FixtureDevice(
|
||||
"setup/cloud_somfy_tahoma_v2_europe.json",
|
||||
"io://1234-1234-6233/12184029",
|
||||
"cover.garden_house_shutter",
|
||||
)
|
||||
GARAGE = FixtureDevice(
|
||||
"setup/cloud_somfy_tahoma_v2_europe.json",
|
||||
"io://1234-1234-6233/1166863",
|
||||
"cover.main_garage_door",
|
||||
)
|
||||
TILTED_WINDOW = FixtureDevice(
|
||||
"setup/local_somfy_tahoma_switch_europe_3.json",
|
||||
"io://1234-5678-9373/10202865",
|
||||
"cover.bedroom_blinds",
|
||||
)
|
||||
# Device with ClosureState=108
|
||||
DYNAMIC_EXTERIOR_VENETIAN_BLIND = FixtureDevice(
|
||||
"setup/local_somfy_tahoma_switch_europe.json",
|
||||
"io://1234-5678-6508/4877511",
|
||||
"cover.dining_room_blinds",
|
||||
)
|
||||
# Device with ClosureState=124
|
||||
POSITIONABLE_ROLLER_SHUTTER_UNO = FixtureDevice(
|
||||
"setup/local_somfy_tahoma_switch_europe_2.json",
|
||||
"io://1234-5678-1516/3656107",
|
||||
"cover.hallway_shutter",
|
||||
)
|
||||
POSITIONABLE_DUAL_ROLLER_SHUTTER = FixtureDevice(
|
||||
"setup/cloud_somfy_tahoma_switch_sc_europe.json",
|
||||
"io://1234-5678-5010/12931361",
|
||||
"cover.basement_roller_shutter",
|
||||
)
|
||||
|
||||
SNAPSHOT_FIXTURES = [
|
||||
AWNING,
|
||||
LOW_SPEED,
|
||||
PERGOLA,
|
||||
RTS,
|
||||
SHUTTER,
|
||||
TILTED_WINDOW,
|
||||
DYNAMIC_EXTERIOR_VENETIAN_BLIND,
|
||||
POSITIONABLE_ROLLER_SHUTTER_UNO,
|
||||
POSITIONABLE_DUAL_ROLLER_SHUTTER,
|
||||
]
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def fixture_platforms() -> Generator[None]:
|
||||
"""Limit platforms to cover only."""
|
||||
with patch("homeassistant.components.overkiz.PLATFORMS", [Platform.COVER]):
|
||||
yield
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"device",
|
||||
SNAPSHOT_FIXTURES,
|
||||
ids=[Path(device.fixture).name for device in SNAPSHOT_FIXTURES],
|
||||
)
|
||||
async def test_cover_entities_snapshot(
|
||||
hass: HomeAssistant,
|
||||
setup_overkiz_integration: SetupOverkizIntegration,
|
||||
entity_registry: er.EntityRegistry,
|
||||
snapshot: SnapshotAssertion,
|
||||
device: FixtureDevice,
|
||||
) -> None:
|
||||
"""Test representative real setups via snapshot."""
|
||||
config_entry = await setup_overkiz_integration(fixture=device.fixture)
|
||||
|
||||
await snapshot_platform(hass, entity_registry, snapshot, config_entry.entry_id)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("device", "service", "command_name", "expected_state"),
|
||||
[
|
||||
(SHUTTER, SERVICE_OPEN_COVER, "open", CoverState.OPENING),
|
||||
pytest.param(
|
||||
AWNING,
|
||||
SERVICE_OPEN_COVER,
|
||||
"deploy",
|
||||
CoverState.OPENING,
|
||||
marks=pytest.mark.xfail(reason="Awning deploy not mapped to opening state"),
|
||||
),
|
||||
(GARAGE, SERVICE_OPEN_COVER, "open", CoverState.OPENING),
|
||||
(SHUTTER, SERVICE_CLOSE_COVER, "close", CoverState.CLOSING),
|
||||
pytest.param(
|
||||
AWNING,
|
||||
SERVICE_CLOSE_COVER,
|
||||
"undeploy",
|
||||
CoverState.CLOSING,
|
||||
marks=pytest.mark.xfail(
|
||||
reason="Awning undeploy not mapped to closing state"
|
||||
),
|
||||
),
|
||||
(GARAGE, SERVICE_CLOSE_COVER, "close", CoverState.CLOSING),
|
||||
(SHUTTER, SERVICE_STOP_COVER, "stop", CoverState.CLOSED),
|
||||
(AWNING, SERVICE_STOP_COVER, "stop", CoverState.CLOSED),
|
||||
(GARAGE, SERVICE_STOP_COVER, "stop", CoverState.CLOSED),
|
||||
],
|
||||
ids=[
|
||||
"open-roller-shutter",
|
||||
"open-awning",
|
||||
"open-garage-door",
|
||||
"close-roller-shutter",
|
||||
"close-awning",
|
||||
"close-garage-door",
|
||||
"stop-roller-shutter",
|
||||
"stop-awning",
|
||||
"stop-garage-door",
|
||||
],
|
||||
)
|
||||
async def test_cover_service_actions(
|
||||
hass: HomeAssistant,
|
||||
setup_overkiz_integration: SetupOverkizIntegration,
|
||||
mock_client: MockOverkizClient,
|
||||
device: FixtureDevice,
|
||||
service: str,
|
||||
command_name: str,
|
||||
expected_state: CoverState,
|
||||
) -> None:
|
||||
"""Test open, close, and stop cover services."""
|
||||
await setup_overkiz_integration(fixture=device.fixture)
|
||||
|
||||
await hass.services.async_call(
|
||||
COVER_DOMAIN,
|
||||
service,
|
||||
{ATTR_ENTITY_ID: device.entity_id},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert hass.states.get(device.entity_id).state == expected_state
|
||||
|
||||
assert_command_call(
|
||||
mock_client,
|
||||
device_url=device.device_url,
|
||||
command_name=command_name,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
(
|
||||
"device",
|
||||
"entity_id",
|
||||
"command_name",
|
||||
"parameters",
|
||||
"position",
|
||||
),
|
||||
[
|
||||
(SHUTTER, SHUTTER.entity_id, "setClosure", [75], 25),
|
||||
(AWNING, AWNING.entity_id, "setDeployment", [80], 80),
|
||||
(
|
||||
LOW_SPEED,
|
||||
"cover.nursery_shutter_low_speed",
|
||||
"setClosureAndLinearSpeed",
|
||||
[65, OverkizCommandParam.LOWSPEED],
|
||||
35,
|
||||
),
|
||||
],
|
||||
ids=["roller-shutter", "awning", "low-speed"],
|
||||
)
|
||||
async def test_cover_set_position(
|
||||
hass: HomeAssistant,
|
||||
setup_overkiz_integration: SetupOverkizIntegration,
|
||||
mock_client: MockOverkizClient,
|
||||
device: FixtureDevice,
|
||||
entity_id: str,
|
||||
command_name: str,
|
||||
parameters: list[Any],
|
||||
position: int,
|
||||
) -> None:
|
||||
"""Test cover position services and mapping."""
|
||||
await setup_overkiz_integration(fixture=device.fixture)
|
||||
|
||||
await hass.services.async_call(
|
||||
COVER_DOMAIN,
|
||||
SERVICE_SET_COVER_POSITION,
|
||||
{ATTR_ENTITY_ID: entity_id, ATTR_POSITION: position},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
assert_command_call(
|
||||
mock_client,
|
||||
device_url=device.device_url,
|
||||
command_name=command_name,
|
||||
parameters=parameters,
|
||||
)
|
||||
|
||||
|
||||
async def test_cover_tilt_services(
|
||||
hass: HomeAssistant,
|
||||
setup_overkiz_integration: SetupOverkizIntegration,
|
||||
mock_client: MockOverkizClient,
|
||||
freezer: FrozenDateTimeFactory,
|
||||
) -> None:
|
||||
"""Test tilt services for a pergola from a full user setup."""
|
||||
await setup_overkiz_integration(fixture=PERGOLA.fixture)
|
||||
|
||||
state = hass.states.get(PERGOLA.entity_id)
|
||||
assert state
|
||||
assert state.attributes[ATTR_CURRENT_TILT_POSITION] == 0
|
||||
assert ATTR_CURRENT_POSITION not in state.attributes
|
||||
assert state.attributes["supported_features"] == (
|
||||
CoverEntityFeature.OPEN_TILT
|
||||
| CoverEntityFeature.CLOSE_TILT
|
||||
| CoverEntityFeature.STOP_TILT
|
||||
| CoverEntityFeature.SET_TILT_POSITION
|
||||
)
|
||||
|
||||
mock_client.execute_command.reset_mock()
|
||||
await hass.services.async_call(
|
||||
COVER_DOMAIN,
|
||||
SERVICE_OPEN_COVER_TILT,
|
||||
{ATTR_ENTITY_ID: PERGOLA.entity_id},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert hass.states.get(PERGOLA.entity_id).state == CoverState.OPENING
|
||||
assert_command_call(
|
||||
mock_client,
|
||||
device_url=PERGOLA.device_url,
|
||||
command_name="openSlats",
|
||||
)
|
||||
|
||||
await async_deliver_events(
|
||||
hass,
|
||||
freezer,
|
||||
mock_client,
|
||||
[
|
||||
build_event(
|
||||
EventName.EXECUTION_STATE_CHANGED.value,
|
||||
device_url=PERGOLA.device_url,
|
||||
exec_id="exec-1",
|
||||
new_state=ExecutionState.COMPLETED.value,
|
||||
)
|
||||
],
|
||||
)
|
||||
assert hass.states.get(PERGOLA.entity_id).state == CoverState.CLOSED
|
||||
|
||||
mock_client.execute_command.reset_mock()
|
||||
await hass.services.async_call(
|
||||
COVER_DOMAIN,
|
||||
SERVICE_CLOSE_COVER_TILT,
|
||||
{ATTR_ENTITY_ID: PERGOLA.entity_id},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert hass.states.get(PERGOLA.entity_id).state == CoverState.CLOSING
|
||||
assert_command_call(
|
||||
mock_client,
|
||||
device_url=PERGOLA.device_url,
|
||||
command_name="closeSlats",
|
||||
)
|
||||
|
||||
mock_client.execute_command.reset_mock()
|
||||
await hass.services.async_call(
|
||||
COVER_DOMAIN,
|
||||
SERVICE_STOP_COVER_TILT,
|
||||
{ATTR_ENTITY_ID: PERGOLA.entity_id},
|
||||
blocking=True,
|
||||
)
|
||||
assert_command_call(
|
||||
mock_client,
|
||||
device_url=PERGOLA.device_url,
|
||||
command_name="stop",
|
||||
)
|
||||
|
||||
mock_client.execute_command.reset_mock()
|
||||
await hass.services.async_call(
|
||||
COVER_DOMAIN,
|
||||
SERVICE_SET_COVER_TILT_POSITION,
|
||||
{ATTR_ENTITY_ID: PERGOLA.entity_id, ATTR_TILT_POSITION: 40},
|
||||
blocking=True,
|
||||
)
|
||||
assert_command_call(
|
||||
mock_client,
|
||||
device_url=PERGOLA.device_url,
|
||||
command_name="setOrientation",
|
||||
parameters=[60],
|
||||
)
|
||||
|
||||
|
||||
async def test_cover_state_updates(
|
||||
hass: HomeAssistant,
|
||||
setup_overkiz_integration: SetupOverkizIntegration,
|
||||
mock_client: MockOverkizClient,
|
||||
freezer: FrozenDateTimeFactory,
|
||||
) -> None:
|
||||
"""Test cover state updates via events and execution tracking."""
|
||||
await setup_overkiz_integration(fixture=SHUTTER.fixture)
|
||||
|
||||
assert hass.states.get(SHUTTER.entity_id).attributes[ATTR_CURRENT_POSITION] == 0
|
||||
|
||||
# Position update via device state change event
|
||||
await async_deliver_events(
|
||||
hass,
|
||||
freezer,
|
||||
mock_client,
|
||||
[
|
||||
build_event(
|
||||
EventName.DEVICE_STATE_CHANGED.value,
|
||||
device_url=SHUTTER.device_url,
|
||||
device_states=[
|
||||
{
|
||||
"name": OverkizState.CORE_CLOSURE.value,
|
||||
"type": 1,
|
||||
"value": 0,
|
||||
},
|
||||
{
|
||||
"name": OverkizState.CORE_TARGET_CLOSURE.value,
|
||||
"type": 1,
|
||||
"value": 0,
|
||||
},
|
||||
{
|
||||
"name": OverkizState.CORE_MOVING.value,
|
||||
"type": 6,
|
||||
"value": False,
|
||||
},
|
||||
{
|
||||
"name": OverkizState.CORE_OPEN_CLOSED.value,
|
||||
"type": 3,
|
||||
"value": OverkizCommandParam.OPEN.value,
|
||||
},
|
||||
],
|
||||
)
|
||||
],
|
||||
)
|
||||
|
||||
state = hass.states.get(SHUTTER.entity_id)
|
||||
assert state.attributes[ATTR_CURRENT_POSITION] == 100
|
||||
assert state.state == CoverState.OPEN
|
||||
|
||||
# Position update to closed
|
||||
await async_deliver_events(
|
||||
hass,
|
||||
freezer,
|
||||
mock_client,
|
||||
[
|
||||
build_event(
|
||||
EventName.DEVICE_STATE_CHANGED.value,
|
||||
device_url=SHUTTER.device_url,
|
||||
device_states=[
|
||||
{
|
||||
"name": OverkizState.CORE_CLOSURE.value,
|
||||
"type": 1,
|
||||
"value": 100,
|
||||
},
|
||||
{
|
||||
"name": OverkizState.CORE_TARGET_CLOSURE.value,
|
||||
"type": 1,
|
||||
"value": 100,
|
||||
},
|
||||
{
|
||||
"name": OverkizState.CORE_MOVING.value,
|
||||
"type": 6,
|
||||
"value": False,
|
||||
},
|
||||
{
|
||||
"name": OverkizState.CORE_OPEN_CLOSED.value,
|
||||
"type": 3,
|
||||
"value": OverkizCommandParam.CLOSED.value,
|
||||
},
|
||||
],
|
||||
)
|
||||
],
|
||||
)
|
||||
|
||||
state = hass.states.get(SHUTTER.entity_id)
|
||||
assert state.attributes[ATTR_CURRENT_POSITION] == 0
|
||||
assert state.state == CoverState.CLOSED
|
||||
|
||||
# Execution tracking: state stays OPENING until execution completes
|
||||
await hass.services.async_call(
|
||||
COVER_DOMAIN,
|
||||
SERVICE_OPEN_COVER,
|
||||
{ATTR_ENTITY_ID: SHUTTER.entity_id},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert hass.states.get(SHUTTER.entity_id).state == CoverState.OPENING
|
||||
|
||||
await async_deliver_events(
|
||||
hass,
|
||||
freezer,
|
||||
mock_client,
|
||||
[
|
||||
build_event(
|
||||
EventName.DEVICE_STATE_CHANGED.value,
|
||||
device_url=SHUTTER.device_url,
|
||||
device_states=[
|
||||
{
|
||||
"name": OverkizState.CORE_CLOSURE.value,
|
||||
"type": 1,
|
||||
"value": 0,
|
||||
},
|
||||
{
|
||||
"name": OverkizState.CORE_TARGET_CLOSURE.value,
|
||||
"type": 1,
|
||||
"value": 0,
|
||||
},
|
||||
{
|
||||
"name": OverkizState.CORE_MOVING.value,
|
||||
"type": 6,
|
||||
"value": False,
|
||||
},
|
||||
{
|
||||
"name": OverkizState.CORE_OPEN_CLOSED.value,
|
||||
"type": 3,
|
||||
"value": OverkizCommandParam.OPEN.value,
|
||||
},
|
||||
],
|
||||
)
|
||||
],
|
||||
)
|
||||
assert hass.states.get(SHUTTER.entity_id).state == CoverState.OPENING
|
||||
|
||||
await async_deliver_events(
|
||||
hass,
|
||||
freezer,
|
||||
mock_client,
|
||||
[
|
||||
build_event(
|
||||
EventName.EXECUTION_STATE_CHANGED.value,
|
||||
device_url=SHUTTER.device_url,
|
||||
exec_id="exec-1",
|
||||
new_state=ExecutionState.COMPLETED.value,
|
||||
)
|
||||
],
|
||||
)
|
||||
assert hass.states.get(SHUTTER.entity_id).state == CoverState.OPEN
|
||||
|
||||
# Unavailability propagates to entity state
|
||||
await async_deliver_events(
|
||||
hass,
|
||||
freezer,
|
||||
mock_client,
|
||||
[
|
||||
build_event(
|
||||
EventName.DEVICE_UNAVAILABLE.value, device_url=SHUTTER.device_url
|
||||
)
|
||||
],
|
||||
)
|
||||
assert hass.states.get(SHUTTER.entity_id).state == STATE_UNAVAILABLE
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("device_states", "expected_state"),
|
||||
[
|
||||
(
|
||||
[
|
||||
{"name": OverkizState.CORE_MOVING.value, "type": 6, "value": True},
|
||||
{"name": OverkizState.CORE_CLOSURE.value, "type": 1, "value": 75},
|
||||
{
|
||||
"name": OverkizState.CORE_TARGET_CLOSURE.value,
|
||||
"type": 1,
|
||||
"value": 20,
|
||||
},
|
||||
],
|
||||
CoverState.OPENING,
|
||||
),
|
||||
(
|
||||
[
|
||||
{"name": OverkizState.CORE_MOVING.value, "type": 6, "value": True},
|
||||
{"name": OverkizState.CORE_CLOSURE.value, "type": 1, "value": 20},
|
||||
{
|
||||
"name": OverkizState.CORE_TARGET_CLOSURE.value,
|
||||
"type": 1,
|
||||
"value": 75,
|
||||
},
|
||||
],
|
||||
CoverState.CLOSING,
|
||||
),
|
||||
],
|
||||
ids=["opening", "closing"],
|
||||
)
|
||||
async def test_vertical_cover_moving_direction(
|
||||
hass: HomeAssistant,
|
||||
setup_overkiz_integration: SetupOverkizIntegration,
|
||||
mock_client: MockOverkizClient,
|
||||
freezer: FrozenDateTimeFactory,
|
||||
device_states: list[dict[str, Any]],
|
||||
expected_state: CoverState,
|
||||
) -> None:
|
||||
"""Test moving direction detection for vertical covers based on current vs target position."""
|
||||
await setup_overkiz_integration(fixture=SHUTTER.fixture)
|
||||
|
||||
await async_deliver_events(
|
||||
hass,
|
||||
freezer,
|
||||
mock_client,
|
||||
[
|
||||
build_event(
|
||||
EventName.DEVICE_STATE_CHANGED.value,
|
||||
device_url=SHUTTER.device_url,
|
||||
device_states=device_states,
|
||||
)
|
||||
],
|
||||
)
|
||||
|
||||
assert hass.states.get(SHUTTER.entity_id).state == expected_state
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("device_states", "expected_state"),
|
||||
[
|
||||
(
|
||||
[
|
||||
{"name": OverkizState.CORE_MOVING.value, "type": 6, "value": True},
|
||||
{
|
||||
"name": OverkizState.CORE_DEPLOYMENT.value,
|
||||
"type": 1,
|
||||
"value": 20,
|
||||
},
|
||||
{
|
||||
"name": OverkizState.CORE_TARGET_CLOSURE.value,
|
||||
"type": 1,
|
||||
"value": 80,
|
||||
},
|
||||
],
|
||||
CoverState.OPENING,
|
||||
),
|
||||
(
|
||||
[
|
||||
{"name": OverkizState.CORE_MOVING.value, "type": 6, "value": True},
|
||||
{
|
||||
"name": OverkizState.CORE_DEPLOYMENT.value,
|
||||
"type": 1,
|
||||
"value": 80,
|
||||
},
|
||||
{
|
||||
"name": OverkizState.CORE_TARGET_CLOSURE.value,
|
||||
"type": 1,
|
||||
"value": 20,
|
||||
},
|
||||
],
|
||||
CoverState.CLOSING,
|
||||
),
|
||||
],
|
||||
ids=["opening", "closing"],
|
||||
)
|
||||
async def test_awning_moving_direction(
|
||||
hass: HomeAssistant,
|
||||
setup_overkiz_integration: SetupOverkizIntegration,
|
||||
mock_client: MockOverkizClient,
|
||||
freezer: FrozenDateTimeFactory,
|
||||
device_states: list[dict[str, Any]],
|
||||
expected_state: CoverState,
|
||||
) -> None:
|
||||
"""Test moving direction detection for awnings based on current vs target position."""
|
||||
await setup_overkiz_integration(fixture=AWNING.fixture)
|
||||
|
||||
await async_deliver_events(
|
||||
hass,
|
||||
freezer,
|
||||
mock_client,
|
||||
[
|
||||
build_event(
|
||||
EventName.DEVICE_STATE_CHANGED.value,
|
||||
device_url=AWNING.device_url,
|
||||
device_states=device_states,
|
||||
)
|
||||
],
|
||||
)
|
||||
|
||||
assert hass.states.get(AWNING.entity_id).state == expected_state
|
||||
|
||||
|
||||
async def test_awning_direct_position_mapping(
|
||||
hass: HomeAssistant,
|
||||
setup_overkiz_integration: SetupOverkizIntegration,
|
||||
mock_client: MockOverkizClient,
|
||||
freezer: FrozenDateTimeFactory,
|
||||
) -> None:
|
||||
"""Test awning deployment uses direct mapping while vertical covers invert."""
|
||||
await setup_overkiz_integration(fixture=AWNING.fixture)
|
||||
|
||||
assert hass.states.get(AWNING.entity_id).attributes[ATTR_CURRENT_POSITION] == 0
|
||||
|
||||
mock_client.execute_command.reset_mock()
|
||||
await hass.services.async_call(
|
||||
COVER_DOMAIN,
|
||||
SERVICE_SET_COVER_POSITION,
|
||||
{ATTR_ENTITY_ID: AWNING.entity_id, ATTR_POSITION: 35},
|
||||
blocking=True,
|
||||
)
|
||||
assert_command_call(
|
||||
mock_client,
|
||||
device_url=AWNING.device_url,
|
||||
command_name="setDeployment",
|
||||
parameters=[35],
|
||||
)
|
||||
|
||||
await async_deliver_events(
|
||||
hass,
|
||||
freezer,
|
||||
mock_client,
|
||||
[
|
||||
build_event(
|
||||
EventName.DEVICE_STATE_CHANGED.value,
|
||||
device_url=AWNING.device_url,
|
||||
device_states=[
|
||||
{
|
||||
"name": OverkizState.CORE_DEPLOYMENT.value,
|
||||
"type": 1,
|
||||
"value": 100,
|
||||
}
|
||||
],
|
||||
)
|
||||
],
|
||||
)
|
||||
assert hass.states.get(AWNING.entity_id).attributes[ATTR_CURRENT_POSITION] == 100
|
||||
Reference in New Issue
Block a user