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
11 changes: 9 additions & 2 deletions pyoverkiz/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -447,9 +447,16 @@ async def unregister_event_listener(self) -> None:
self.event_listener_id = None

@retry_on_auth_error
async def get_current_execution(self, exec_id: str) -> Execution:
"""Get a currently running execution by its exec_id."""
async def get_current_execution(self, exec_id: str) -> Execution | None:
"""Get a currently running execution by its exec_id.

Returns None if the execution does not exist.
"""
response = await self._get(f"exec/current/{exec_id}")

if not response or not isinstance(response, dict):
return None
Comment thread
iMicknl marked this conversation as resolved.

return Execution(**decamelize(response))

@retry_on_auth_error
Expand Down
8 changes: 8 additions & 0 deletions pyoverkiz/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,14 @@ class UnknownUserError(BaseOverkizError):
"""Raised when an unknown user is provided."""


class NoSuchDeviceError(BaseOverkizError):
"""Raised when the requested device does not exist."""


class NoSuchActionGroupError(BaseOverkizError):
"""Raised when the requested action group does not exist."""


class UnknownObjectError(BaseOverkizError):
"""Raised when an unknown object is provided."""

Expand Down
26 changes: 17 additions & 9 deletions pyoverkiz/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -805,8 +805,11 @@ class Execution:
id: str
description: str
owner: str = field(repr=obfuscate_email)
state: str
state: ExecutionState
action_group: ActionGroup
start_time: int | None = None
execution_type: ExecutionType | None = None
execution_sub_type: ExecutionSubType | None = None

def __init__(
self,
Expand All @@ -815,14 +818,22 @@ def __init__(
owner: str,
state: str,
action_group: dict[str, Any],
start_time: int | None = None,
execution_type: str | None = None,
execution_sub_type: str | None = None,
**_: Any,
):
"""Initialize Execution object from API fields."""
self.id = id
self.description = description
self.owner = owner
self.state = state
self.state = ExecutionState(state)
self.action_group = ActionGroup(**action_group)
self.start_time = start_time
self.execution_type = ExecutionType(execution_type) if execution_type else None
self.execution_sub_type = (
ExecutionSubType(execution_sub_type) if execution_sub_type else None
)


@define(init=False, kw_only=True)
Expand Down Expand Up @@ -858,7 +869,7 @@ class ActionGroup:
is composed of one or more commands to be executed on that device.
"""

id: str = field(repr=obfuscate_id)
id: str | None = field(default=None, repr=obfuscate_id)
creation_time: int | None = None
last_update_time: int | None = None
label: str = field(repr=obfuscate_string)
Expand All @@ -869,7 +880,7 @@ class ActionGroup:
notification_text: str | None = None
notification_title: str | None = None
actions: list[Action]
oid: str = field(repr=obfuscate_id)
oid: str | None = field(default=None, repr=obfuscate_id)

def __init__(
self,
Expand All @@ -888,10 +899,7 @@ def __init__(
**_: Any,
) -> None:
"""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.id = oid or id
self.creation_time = creation_time
self.last_update_time = last_update_time
self.label = (
Expand All @@ -904,7 +912,7 @@ def __init__(
self.notification_text = notification_text
self.notification_title = notification_title
self.actions = [Action(**action) for action in actions]
self.oid = cast(str, oid or id)
self.oid = oid or id


@define(init=False, kw_only=True)
Expand Down
4 changes: 4 additions & 0 deletions pyoverkiz/response_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
MissingAPIKeyError,
MissingAuthorizationTokenError,
NoRegisteredEventListenerError,
NoSuchActionGroupError,
NoSuchDeviceError,
NoSuchResourceError,
NoSuchTokenError,
NotAuthenticatedError,
Expand All @@ -46,6 +48,8 @@
("INVALID_FIELD_VALUE", None, ActionGroupSetupNotFoundError),
("INVALID_API_CALL", None, NoSuchResourceError),
("EXEC_QUEUE_FULL", None, ExecutionQueueFullError),
("NO_SUCH_DEVICE", None, NoSuchDeviceError),
("NO_SUCH_ACTION_GROUP", None, NoSuchActionGroupError),
# --- errorCode + message substring ---
("AUTHENTICATION_ERROR", "Too many requests", TooManyRequestsError),
("AUTHENTICATION_ERROR", "Bad credentials", BadCredentialsError),
Expand Down
17 changes: 17 additions & 0 deletions tests/fixtures/endpoints/device-states.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[
{
"name": "core:StatusState",
"type": 3,
"value": "available"
},
{
"name": "core:ClosureState",
"type": 1,
"value": 0
},
{
"name": "core:OpenClosedState",
"type": 3,
"value": "open"
}
]
1 change: 1 addition & 0 deletions tests/fixtures/endpoints/events-register.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"id": "a70f6d96-0a19-0483-72d9-ac5f6bd7da26"}
1 change: 1 addition & 0 deletions tests/fixtures/endpoints/exec-apply.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"execId": "ee7a5676-c68f-43a3-956d-6f5efc745954"}
1 change: 1 addition & 0 deletions tests/fixtures/endpoints/exec-current-empty-list.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
1 change: 1 addition & 0 deletions tests/fixtures/endpoints/exec-current-empty-object.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
1 change: 1 addition & 0 deletions tests/fixtures/endpoints/exec-schedule.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"triggerId": "abc12345-def6-7890-abcd-ef1234567890"}
52 changes: 52 additions & 0 deletions tests/fixtures/endpoints/history-executions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
[
{
"id": "699dd967-0a19-0481-7a62-99b990a2feb8",
"eventTime": 1767003511145,
"owner": "[email protected]",
"source": "modem",
"endTime": 1767003514000,
"effectiveStartTime": 1767003511500,
"duration": 2855,
"label": "close - RTS Roller Shutter",
"type": "ACTUATOR",
"state": "COMPLETED",
"failureType": "NO_FAILURE",
"commands": [
{
"deviceURL": "rts://2025-8464-6867/16756006",
"command": "close",
"parameters": [],
"rank": 0,
"dynamic": false,
"state": "COMPLETED",
"failureType": "NO_FAILURE"
}
],
"executionType": "Immediate execution",
"executionSubType": "MANUAL_CONTROL"
},
{
"id": "b2c3d4e5-f6a7-8901-bcde-f23456789012",
"eventTime": 1767002400000,
"owner": "[email protected]",
"source": "modem",
"duration": 0,
"label": "open - RTS Roller Shutter",
"type": "ACTUATOR",
"state": "FAILED",
"failureType": "CMDCANCELLED",
"commands": [
{
"deviceURL": "rts://2025-8464-6867/16756006",
"command": "open",
"parameters": [],
"rank": 0,
"dynamic": false,
"state": "FAILED",
"failureType": "CMDCANCELLED"
}
],
"executionType": "Immediate execution",
"executionSubType": "MANUAL_CONTROL"
}
]
25 changes: 25 additions & 0 deletions tests/fixtures/endpoints/setup-places.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"creationTime": 1650000000000,
"lastUpdateTime": 1767003511145,
"label": "My House",
"type": 0,
"oid": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
"subPlaces": [
{
"creationTime": 1650000100000,
"lastUpdateTime": 1767003511145,
"label": "Living Room",
"type": 1,
"oid": "11111111-2222-3333-4444-555555555555",
"subPlaces": []
},
{
"creationTime": 1650000200000,
"lastUpdateTime": null,
"label": "Bedroom",
"type": 1,
"oid": "66666666-7777-8888-9999-aaaaaaaaaaaa",
"subPlaces": []
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"errorCode":"INVALID_FIELD_VALUE","error":"Unable to determine action group setup (no setup for gateway #0000-0000-0000)"}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"errorCode":"NO_SUCH_ACTION_GROUP","error":"No such action group : 00000000-0000-0000-0000-000000000000"}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"errorCode":"NO_SUCH_RESSOURCE","error":"No such controllable : io:NonExistentDeviceControllable"}
1 change: 1 addition & 0 deletions tests/fixtures/exceptions/cloud/no-such-ui-profile.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"errorCode":"NO_SUCH_RESSOURCE","error":"No such core UI profile or form-factor : NonExistentProfile"}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"errorCode":"RESOURCE_ACCESS_DENIED","error":"Security exception : Device setup mismatch"}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"errorCode":"RESOURCE_ACCESS_DENIED","error":"Security exception : Gateway #0000-0000-0000 does not belong to setup 15eaf55a-8af9-483b-ae4a-ffd4254fd762"}
26 changes: 26 additions & 0 deletions tests/fixtures/exec/current-single.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"startTime": 1767003511145,
"owner": "[email protected]",
"actionGroup": {
"label": "Execution via Home Assistant",
"shortcut": false,
"notificationTypeMask": 0,
"notificationCondition": "NEVER",
"actions": [
{
"deviceURL": "rts://1234-5678-1234/12345678",
"commands": [
{
"type": 1,
"name": "close"
}
]
}
]
},
"description": "Execution : Execution via Home Assistant",
"id": "699dd967-0a19-0481-7a62-99b990a2feb8",
"state": "TRANSMITTED",
"executionType": "Immediate execution",
"executionSubType": "MANUAL_CONTROL"
}
Loading