Skip to content

Commit

Permalink
Support creating scenes with controller trigger (#74)
Browse files Browse the repository at this point in the history
* Support creating scenes with controller trigger

* Make `Trigger.id` optional

* Handle sunset triggers
  • Loading branch information
bjorncs authored Apr 26, 2024
1 parent 7bae4e9 commit e1f5692
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 9 deletions.
17 changes: 16 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -371,11 +371,26 @@ Triggers look like this:

```python
class Trigger(BaseIkeaModel):
id: str
id: Optional[str] = None
type: str
triggered_at: Optional[datetime.datetime] = None
disabled: bool
trigger: Optional[TriggerDetails] = None
```

Example how to create scene with trigger:
```python
from dirigera.devices.scene import Info, Icon, Trigger, SceneType, TriggerDetails, ControllerType, ClickPattern

scene = dirigera_hub.create_scene(
info=Info(name="Scene with trigger", icon=Icon.SCENES_HEART),
scene_type=SceneType.USER_SCENE,
triggers=[
Trigger(type="app", disabled=False),
Trigger(type="controller", disabled=False,
trigger=TriggerDetails(clickPattern=ClickPattern.SINGLE_PRESS, buttonIndex=0,
deviceId="0000aaaa-0000-0000-aa00-0a0aa0a000a0_1",
controllerType=ControllerType.SHORTCUT_CONTROLLER))])
```

All available icons can be found here: [Icons](./src/dirigera/devices/scene.py)
Expand Down
23 changes: 22 additions & 1 deletion src/dirigera/devices/scene.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,31 @@ class Info(BaseIkeaModel):


class Trigger(BaseIkeaModel):
id: str
id: Optional[str] = None # Optional to allow creation of Trigger instances for create_scene()
type: str
triggered_at: Optional[datetime.datetime] = None
disabled: bool
trigger: Optional[TriggerDetails] = None


class TriggerDetails(BaseIkeaModel):
days: Optional[List[str]] = None
controllerType: Optional[ControllerType] = None
buttonIndex: Optional[int] = None
clickPattern: Optional[ClickPattern] = None
deviceId: Optional[str] = None
offset: Optional[int] = None
type: Optional[str] = None


class ControllerType(Enum):
SHORTCUT_CONTROLLER = "shortcutController"


class ClickPattern(Enum):
LONG_PRESS = "longPress"
DOUBLE_PRESS = "doublePress"
SINGLE_PRESS = "singlePress"


class ActionAttributes(BaseIkeaModel, extra="allow"):
Expand Down
82 changes: 75 additions & 7 deletions tests/test_scenes.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from typing import Any, Dict
import pytest
from src.dirigera.hub.abstract_smart_home_hub import FakeDirigeraHub
from src.dirigera.devices.scene import Scene, dict_to_scene
from src.dirigera.devices.scene import Scene, dict_to_scene, ControllerType

TEST_ID = "c9bbf831-6dcd-4442-8195-53eedb66a598"
TEST_NAME = "Tesscene"
Expand Down Expand Up @@ -57,7 +57,7 @@ def test_trigger(fake_scene: Scene, fake_client: FakeDirigeraHub) -> None:


def test_dict_to_scene(fake_client: FakeDirigeraHub) -> None:
data: Dict[str, Any] = {
data1: Dict[str, Any] = {
"id": "c9bbf831-6dcd-4442-8195-53eedb66a598",
"info": {"name": "Tesscene", "icon": "scenes_clean_sparkles"},
"type": "userScene",
Expand All @@ -84,10 +84,78 @@ def test_dict_to_scene(fake_client: FakeDirigeraHub) -> None:
"lastUndo": "2023-08-27T10:29:33.049Z",
}

scene = dict_to_scene(data, fake_client)
assert scene.id == TEST_ID
assert scene.info.name == TEST_NAME
assert scene.info.icon.value == TEST_ICON
assert scene.last_completed == datetime.datetime.strptime(
scene1 = dict_to_scene(data1, fake_client)
assert scene1.id == TEST_ID
assert scene1.info.name == TEST_NAME
assert scene1.info.icon.value == TEST_ICON
assert scene1.last_completed == datetime.datetime.strptime(
TEST_LAST_COMPLETED, "%Y-%m-%dT%H:%M:%S.%f%z"
)

data2: Dict[str, Any] = {
"id": "00a0a00a-0aa0-0000-a000-00a0000a0a00",
"info": {
"name": "Night",
"icon": "scenes_clean_sparkles"
},
"type": "userScene",
"triggers": [
{
"id": "0000a0a0-0a00-000a-0a00-aaaaaa000000",
"type": "app",
"triggeredAt": "2024-04-23T21:34:51.619Z",
"disabled": False
},
{
"id": "a0000000-a000-0000-aaaa-0aaa000aa000",
"type": "controller",
"triggeredAt": "2024-04-20T05:49:20.178Z",
"disabled": False,
"trigger": {
"days": [
"Mon",
"Tue",
"Wed",
"Thu",
"Fri",
"Sat",
"Sun"
],
"controllerType": "shortcutController",
"clickPattern": "doublePress",
"buttonIndex": 0,
"deviceId": "0000aaaa-0000-0000-aa00-0a0aa0a000a0_2"
}
},
{
"id": "a0000000-a000-0000-aaaa-0aaa000aa000",
"type": "sunriseSunset",
"triggeredAt": "2024-04-24T17:49:00.989Z",
"disabled": False,
"trigger": {
"days": [
"Tue",
"Wed",
"Sun",
"Mon",
"Fri",
"Sat",
"Thu"
],
"type": "sunset",
"offset": 0
},
"nextTriggerAt": "2024-04-25T17:49:00.000Z"
}
],
"actions": [],
"commands": [],
"createdAt": "2023-11-06T22:10:14.806Z",
"lastCompleted": "2024-04-24T05:13:24.352Z",
"lastTriggered": "2024-04-24T05:13:24.352Z",
"undoAllowedDuration": 30
}

scene2 = dict_to_scene(data2, fake_client)
assert scene2.triggers[1].trigger is not None
assert scene2.triggers[1].trigger.controllerType == ControllerType.SHORTCUT_CONTROLLER

0 comments on commit e1f5692

Please sign in to comment.