Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions pyoverkiz/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
UnknownUserException,
)
from pyoverkiz.models import (
ActionGroup,
Command,
Device,
Event,
Expand All @@ -82,7 +83,6 @@
OptionParameter,
OverkizServer,
Place,
Scenario,
Setup,
State,
)
Expand Down Expand Up @@ -665,10 +665,12 @@ async def execute_commands(
return cast(str, response["execId"])

@retry_on_auth_error
async def get_scenarios(self) -> list[Scenario]:
"""List the scenarios."""
async def get_action_groups(self) -> list[ActionGroup]:
"""List the action groups (scenarios)."""
response = await self.__get("actionGroups")
return [Scenario(**scenario) for scenario in humps.decamelize(response)]
return [
ActionGroup(**action_group) for action_group in humps.decamelize(response)
]

@retry_on_auth_error
async def get_places(self) -> Place:
Expand Down
28 changes: 16 additions & 12 deletions pyoverkiz/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -574,23 +574,23 @@ class Execution:
description: str
owner: str = field(repr=obfuscate_email)
state: str
action_group: list[dict[str, Any]]
action_group: ActionGroup

def __init__(
self,
id: str,
description: str,
owner: str,
state: str,
action_group: list[dict[str, Any]],
action_group: dict[str, Any],
**_: Any,
):
"""Initialize Execution object from API fields."""
self.id = id
self.description = description
self.owner = owner
self.state = state
self.action_group = action_group
self.action_group = ActionGroup(**action_group)


@define(init=False, kw_only=True)
Expand All @@ -607,18 +607,18 @@ def __init__(self, device_url: str, commands: list[dict[str, Any]]):


@define(init=False, kw_only=True)
class Scenario:
class ActionGroup:
"""An action group is composed of one or more actions.

Each action is related to a single setup device (designated by its device URL) and
is composed of one or more commands to be executed on that device.
"""

id: str = field(repr=obfuscate_id)
creation_time: int
creation_time: int | None = None
last_update_time: int | None = None
label: str = field(repr=obfuscate_string)
metadata: str
metadata: str | None = None
shortcut: bool | None = None
notification_type_mask: int | None = None
notification_condition: str | None = None
Expand All @@ -629,10 +629,11 @@ class Scenario:

def __init__(
self,
creation_time: int,
metadata: str,
actions: list[dict[str, Any]],
oid: str,
creation_time: int | None = None,
metadata: str | None = None,
oid: str | None = None,
id: str | None = None,
last_update_time: int | None = None,
label: str | None = None,
shortcut: bool | None = None,
Expand All @@ -642,8 +643,11 @@ def __init__(
notification_title: str | None = None,
**_: Any,
) -> None:
"""Initialize Scenario (action group) from API data."""
self.id = oid
"""Initialize ActionGroup from API data and convert nested actions."""
if oid is None and id is None:
raise ValueError("Either 'oid' or 'id' must be provided")

self.id = cast(str, oid or id)
self.creation_time = creation_time
self.last_update_time = last_update_time
self.label = (
Expand All @@ -656,7 +660,7 @@ def __init__(
self.notification_text = notification_text
self.notification_title = notification_title
self.actions = [Action(**action) for action in actions]
self.oid = oid
self.oid = cast(str, oid or id)


@define(init=False, kw_only=True)
Expand Down
37 changes: 37 additions & 0 deletions tests/fixtures/exec/current-tahoma-switch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
[
{
"startTime": 1767003511145,
"owner": "somfy@imick.nl",
"actionGroup": {
"label": "Execution via Home Assistant",
"shortcut": false,
"notificationTypeMask": 0,
"notificationCondition": "NEVER",
"actions": [
{
"deviceURL": "rts://2025-8464-6867/16756006",
"commands": [
{
"type": 1,
"name": "close"
}
]
},
{
"deviceURL": "rts://2025-8464-6867/16719623",
"commands": [
{
"type": 1,
"name": "identify"
}
]
}
]
},
"description": "Execution : Execution via Home Assistant",
"id": "699dd967-0a19-0481-7a62-99b990a2feb8",
"state": "TRANSMITTED",
"executionType": "Immediate execution",
"executionSubType": "MANUAL_CONTROL"
}
]
16 changes: 8 additions & 8 deletions tests/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,7 @@ async def test_get_setup_option(
],
)
@pytest.mark.asyncio
async def test_get_scenarios(
async def test_get_action_groups(
self,
client: OverkizClient,
fixture_name: str,
Expand All @@ -435,16 +435,16 @@ async def test_get_scenarios(
resp = MockResponse(action_group_mock.read())

with patch.object(aiohttp.ClientSession, "get", return_value=resp):
scenarios = await client.get_scenarios()
action_groups = await client.get_action_groups()

assert len(scenarios) == scenario_count
assert len(action_groups) == scenario_count

for scenario in scenarios:
assert scenario.oid
assert scenario.label is not None
assert scenario.actions
for action_group in action_groups:
assert action_group.oid
assert action_group.label is not None
assert action_group.actions

for action in scenario.actions:
for action in action_group.actions:
assert action.device_url
assert action.commands

Expand Down