-
-
Notifications
You must be signed in to change notification settings - Fork 71
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(action-type): add new concept of action types to run different t…
…ype of actions related to #173
- Loading branch information
Showing
48 changed files
with
703 additions
and
387 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
from typing import TYPE_CHECKING, Dict, List, Type | ||
|
||
from cx_const import ActionEvent, CustomAction, CustomActions | ||
from cx_core.action_type.base import ActionType | ||
from cx_core.action_type.call_service_action_type import CallServiceActionType | ||
from cx_core.action_type.delay_action_type import DelayActionType | ||
from cx_core.action_type.predefined_action_type import PredefinedActionType | ||
from cx_core.action_type.scene_action_type import SceneActionType | ||
|
||
if TYPE_CHECKING: | ||
from cx_core import Controller | ||
|
||
ActionsMapping = Dict[ActionEvent, List[ActionType]] | ||
|
||
action_type_mapping: Dict[str, Type[ActionType]] = { | ||
"action": PredefinedActionType, | ||
"service": CallServiceActionType, | ||
"scene": SceneActionType, | ||
"delay": DelayActionType, | ||
} | ||
|
||
|
||
def parse_actions(controller: "Controller", data: CustomActions) -> List[ActionType]: | ||
actions: CustomActions | ||
if isinstance(data, (list, tuple)): | ||
actions = list(data) | ||
else: | ||
actions = [data] | ||
|
||
return [_parse_action(controller, action) for action in actions] | ||
|
||
|
||
def _parse_action(controller: "Controller", action: CustomAction) -> ActionType: | ||
if isinstance(action, str): | ||
return PredefinedActionType(controller, {"action": action}) | ||
try: | ||
return next( | ||
action_type(controller, action) | ||
for key in action | ||
for action_type_key, action_type in action_type_mapping.items() | ||
if key == action_type_key | ||
) | ||
except StopIteration: | ||
raise ValueError( | ||
f"Not able to parse `{action}`. Available keys are: {action_type_mapping.keys()}" | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
from abc import ABC, abstractmethod | ||
from typing import TYPE_CHECKING, Any, Dict, Optional | ||
|
||
from cx_core.integration import EventData | ||
|
||
if TYPE_CHECKING: | ||
from cx_core import Controller | ||
|
||
|
||
class ActionType(ABC): | ||
controller: "Controller" | ||
|
||
def __init__(self, controller: "Controller", action: Dict[str, Any]) -> None: | ||
self.controller = controller | ||
self.initialize(**action) | ||
|
||
def initialize(self, **kwargs) -> None: | ||
pass | ||
|
||
@abstractmethod | ||
async def run(self, extra: Optional[EventData] = None) -> None: | ||
raise NotImplementedError | ||
|
||
def __str__(self) -> str: | ||
return f"{self.__class__.__name__}" |
28 changes: 28 additions & 0 deletions
28
apps/controllerx/cx_core/action_type/call_service_action_type.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
from typing import Any, Dict, Optional | ||
|
||
from cx_core.action_type.base import ActionType | ||
from cx_core.integration import EventData | ||
|
||
|
||
class CallServiceActionType(ActionType): | ||
service: str | ||
entity_id: Optional[str] | ||
data: Dict[str, Any] | ||
|
||
def initialize(self, **kwargs) -> None: | ||
self.service = kwargs["service"] | ||
self.entity_id = kwargs.get("entity_id") | ||
self.data = kwargs.get("data", {}) | ||
|
||
async def run(self, extra: Optional[EventData] = None) -> None: | ||
if self.entity_id: | ||
if "entity_id" in self.data: | ||
del self.data["entity_id"] | ||
await self.controller.call_service( | ||
self.service, entity_id=self.entity_id, **self.data | ||
) | ||
else: | ||
await self.controller.call_service(self.service, **self.data) | ||
|
||
def __str__(self) -> str: | ||
return f"Service ({self.service})" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
from typing import Optional | ||
|
||
from cx_core.action_type.base import ActionType | ||
from cx_core.integration import EventData | ||
|
||
|
||
class DelayActionType(ActionType): | ||
delay: int | ||
|
||
def initialize(self, **kwargs) -> None: | ||
self.delay = kwargs["delay"] | ||
|
||
async def run(self, extra: Optional[EventData] = None) -> None: | ||
await self.controller.sleep(self.delay) | ||
|
||
def __str__(self) -> str: | ||
return f"Delay ({self.delay} seconds)" |
39 changes: 39 additions & 0 deletions
39
apps/controllerx/cx_core/action_type/predefined_action_type.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import inspect | ||
from typing import Optional | ||
|
||
from cx_const import ActionFunctionWithParams, PredefinedActionsMapping, TypeAction | ||
from cx_core.action_type.base import ActionType | ||
from cx_core.integration import EventData | ||
|
||
|
||
def _get_action(action_value: TypeAction) -> ActionFunctionWithParams: | ||
if isinstance(action_value, tuple): | ||
return action_value | ||
else: | ||
return (action_value, tuple()) | ||
|
||
|
||
class PredefinedActionType(ActionType): | ||
action_key: str | ||
predefined_actions_mapping: PredefinedActionsMapping | ||
|
||
def initialize(self, **kwargs) -> None: | ||
self.action_key = kwargs["action"] | ||
self.predefined_actions_mapping = ( | ||
self.controller.get_predefined_actions_mapping() | ||
) | ||
if self.action_key not in self.predefined_actions_mapping: | ||
raise ValueError( | ||
f"`{self.action_key}` is not one of the predefined actions." | ||
f"Available actions are: {list(self.predefined_actions_mapping.keys())}" | ||
) | ||
|
||
async def run(self, extra: Optional[EventData] = None) -> None: | ||
action, args = _get_action(self.predefined_actions_mapping[self.action_key]) | ||
if "extra" in set(inspect.signature(action).parameters): | ||
await action(*args, extra=extra) | ||
else: | ||
await action(*args) | ||
|
||
def __str__(self) -> str: | ||
return f"Predefined ({self.action_key})" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
from typing import Optional | ||
|
||
from cx_core.action_type.base import ActionType | ||
from cx_core.integration import EventData | ||
|
||
|
||
class SceneActionType(ActionType): | ||
scene: str | ||
|
||
def initialize(self, **kwargs) -> None: | ||
self.scene = kwargs["scene"] | ||
|
||
async def run(self, extra: Optional[EventData] = None) -> None: | ||
await self.controller.call_service("scene/turn_on", entity_id=self.scene) | ||
|
||
def __str__(self) -> str: | ||
return f"Scene ({self.scene})" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.