Skip to content

Commit

Permalink
feat(controller): allowing to define action_delta per action
Browse files Browse the repository at this point in the history
  • Loading branch information
xaviml committed Feb 6, 2021
1 parent 15634e6 commit 173304c
Show file tree
Hide file tree
Showing 5 changed files with 27 additions and 21 deletions.
10 changes: 7 additions & 3 deletions apps/controllerx/cx_core/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ class Controller(Hass, Mqtt):
action_delay_handles: Dict[ActionEvent, Optional[float]]
multiple_click_actions: Set[ActionEvent]
action_delay: Dict[ActionEvent, int]
action_delta: int
action_delta: Dict[ActionEvent, int]
action_times: Dict[str, float]
multiple_click_action_times: Dict[str, float]
click_counter: Counter[ActionEvent]
Expand Down Expand Up @@ -133,7 +133,11 @@ async def init(self) -> None:
self.action_handles = defaultdict(lambda: None)

# Action delta
self.action_delta = self.args.get("action_delta", DEFAULT_ACTION_DELTA)
self.action_delta = self.get_mapping_per_action(
self.actions_mapping,
custom=self.args.get("action_delta"),
default=DEFAULT_ACTION_DELTA,
)
self.action_times = defaultdict(lambda: 0.0)

# Multiple click
Expand Down Expand Up @@ -268,7 +272,7 @@ async def handle_action(
previous_call_time = self.action_times[action_key]
now = time.time() * 1000
self.action_times[action_key] = now
if now - previous_call_time > self.action_delta:
if now - previous_call_time > self.action_delta[action_key]:
await self.call_action(action_key, extra=extra)
elif action_key in self.multiple_click_actions:
now = time.time() * 1000
Expand Down
26 changes: 13 additions & 13 deletions docs/start/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,19 +63,19 @@ otherwise they will be parsed as boolean variables (True and False).
These are the generic app parameters for all type of controllers. You can see the rest in [here](type-configuration).
| key | type | value | description |
| ---------------------- | -------------- | ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `module`\* | string | `controllerx` | The Python module |
| `class`\* | string | `E1810Controller` | The Python class. Check the classes for each controller on the [supported controllers](/controllerx/controllers) page. |
| `controller`\* | string \| list | `sensor.controller` or `hue_switch1, hue_switch2` | This is the controller id, which will depend on the integration. See [here](/controllerx/others/extract-controller-id) to know how to get the controller id. |
| `integration`\* | string \| dict | `z2m`, `deconz` or `zha` | This is the integration that the device was integrated. |
| `actions` | list | All actions | This is a list of actions to be included and controlled by the app. To see which actions has each controller check the individual controller pages in [here](/controllerx/controllers). This attribute cannot be used together with `excluded_actions`. |
| `excluded_actions` | list | Empty list | This is a list of actions to be excluded. To see which actions has each controller check the individual controller pages in [here](/controllerx/controllers). This attribute cannot be used together with `actions`. |
| `action_delta` | int | 300 | This is the threshold time between the previous action and the next one (being the same action). If the time difference between the two actions is less than this attribute, then the action won't be called. I recommend changing this if you see the same action being called twice. |
| `multiple_click_delay` | int | 500 | Indicates the delay (in milliseconds) when a multiple click action should be trigger. The higher the number, the more time there can be between clicks, but there will be more delay for the action to be triggered. |
| `action_delay` | dict \| int | - | This can be used to set a delay to each action. By default, the delay for all actions is 0. If defining a map, the key for the map is the action and the value is the delay in seconds. Otherwise, we can set a default time like `action_delay: 10`, and this will add a delay to all actions. |
| `mapping` | dict | - | This can be used to replace the behaviour of the controller and manually select what each button should be doing. By default it will ignore this parameter. Read more about it in [here](/controllerx/advanced/custom-controllers). The functionality included in this attribute will remove the default mapping. |
| `merge_mapping` | dict | - | This can be used to merge the default mapping from the controller and manually select what each button should be doing. By default it will ignore this parameter. Read more about it in [here](/controllerx/advanced/custom-controllers). The functionality included in this attribute is added on top of the default mapping. |
| key | type | value | description |
| ---------------------- | -------------- | ------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `module`\* | string | `controllerx` | The Python module |
| `class`\* | string | `E1810Controller` | The Python class. Check the classes for each controller on the [supported controllers](/controllerx/controllers) page. |
| `controller`\* | string \| list | `sensor.controller` or `hue_switch1, hue_switch2` | This is the controller id, which will depend on the integration. See [here](/controllerx/others/extract-controller-id) to know how to get the controller id. |
| `integration`\* | string \| dict | `z2m`, `deconz` or `zha` | This is the integration that the device was integrated. |
| `actions` | list | All actions | This is a list of actions to be included and controlled by the app. To see which actions has each controller check the individual controller pages in [here](/controllerx/controllers). This attribute cannot be used together with `excluded_actions`. |
| `excluded_actions` | list | Empty list | This is a list of actions to be excluded. To see which actions has each controller check the individual controller pages in [here](/controllerx/controllers). This attribute cannot be used together with `actions`. |
| `action_delta` | dict \| int | 300 | This is the threshold time between the previous action and the next one (being the same action). If the time difference between the two actions is less than this attribute, then the action won't be called. I recommend changing this if you see the same action being called twice. A different `action_delta` per action can be defined in a mapping. |
| `multiple_click_delay` | int | 500 | Indicates the delay (in milliseconds) when a multiple click action should be trigger. The higher the number, the more time there can be between clicks, but there will be more delay for the action to be triggered. |
| `action_delay` | dict \| int | - | This can be used to set a delay to each action. By default, the delay for all actions is 0. If defining a map, the key for the map is the action and the value is the delay in seconds. Otherwise, we can set a default time like `action_delay: 10`, and this will add a delay to all actions. |
| `mapping` | dict | - | This can be used to replace the behaviour of the controller and manually select what each button should be doing. By default it will ignore this parameter. Read more about it in [here](/controllerx/advanced/custom-controllers). The functionality included in this attribute will remove the default mapping. |
| `merge_mapping` | dict | - | This can be used to merge the default mapping from the controller and manually select what each button should be doing. By default it will ignore this parameter. Read more about it in [here](/controllerx/advanced/custom-controllers). The functionality included in this attribute is added on top of the default mapping. |

Integration dictionary for `integration` attribute.

Expand Down
6 changes: 4 additions & 2 deletions tests/integ_tests/other_action_delta_attr/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ light_chambre_chevet:
integration: zha
light: light.chevet
smooth_power_on: true
action_delta: 500
action_delta:
on_hold: 500
off_hold: 500
merge_mapping:
on_hold:
- service: cover.open_cover
Expand All @@ -14,4 +16,4 @@ light_chambre_chevet:
off_hold:
- service: cover.open_cover
data:
entity_id: cover.chambre
entity_id: cover.chambre
2 changes: 1 addition & 1 deletion tests/unit_tests/cx_core/controller_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ async def test_handle_action(
expected_calls: int,
fake_action_type: ActionType,
):
sut.action_delta = action_delta
sut.action_delta = {action_called: action_delta}
sut.action_times = defaultdict(lambda: 0)

actions_mapping: ActionsMapping = {
Expand Down
4 changes: 2 additions & 2 deletions tests/unit_tests/cx_core/custom_controller_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,13 @@ async def test_custom_controllers(
"switch": "switch.test_switch",
"cover": "cover.test_cover",
"mapping": mapping,
"action_delta": 0,
}
mocked = mocker.patch.object(sut, mock_function)
monkeypatch.setattr(sut, "get_entity_state", fake_fn(async_=True, to_return="0"))

# SUT
await sut.initialize()
sut.action_delta = 0
await sut.handle_action(action_input)

# Check
Expand Down Expand Up @@ -150,12 +150,12 @@ async def test_call_service_controller(
"controller": "test_controller",
"integration": integration,
"mapping": {"action": services},
"action_delta": 0,
}
call_service_stub = mocker.patch.object(Hass, "call_service")

# SUT
await sut.initialize()
sut.action_delta = 0
await sut.handle_action("action")

# Checks
Expand Down

0 comments on commit 173304c

Please sign in to comment.