Skip to content

Commit

Permalink
https://github.com/andgineer/docker-amazon-dash-button-hack/issues/24
Browse files Browse the repository at this point in the history
refactored bounce protection logic
  • Loading branch information
andgineer committed Sep 24, 2023
1 parent f126bcc commit 306e276
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 19 deletions.
2 changes: 1 addition & 1 deletion amazon-dash-private/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"ifttt_key_file_name": "../amazon-dash-private/ifttt-key.json",
"openweathermap_key_file_name": "../amazon-dash-private/openweathermap-key.json",
"images_folder": "../amazon-dash-private/images/",
"chatter_delay": 5,
"bounce_delay": 5,
"dashboards": {
"anna_work_out": {
"summary": "Anna work-out",
Expand Down
6 changes: 3 additions & 3 deletions docs/settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,15 @@
"images_folder": "../amazon-dash-private/images/"
```

### `chatter_delay`
### `bounce_delay`

- **Type**: Integer
- **Description**: The delay (in seconds) before the system will respond or react to a subsequent trigger. This can prevent rapid, repeated triggers from overloading the system.
- **Description**: The delay (in seconds) before the system will respond or react to a subsequent trigger. This can prevent from unintendent multiple presses.

**Example**:

```json
"chatter_delay": 5
"bounce_delay": 5
```

### `dashboards`
Expand Down
33 changes: 22 additions & 11 deletions src/amazon_dash.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

from action import Action

CHATTER_DELAY = 5
BOUNCE_DELAY = 5
NO_SETTINGS_FILE = """\nNo {} found. \nIf you run application in docker container you
should connect volume with setting files, like
-v $PWD/amazon-dash-private:/amazon-dash-private:ro"""
Expand All @@ -31,10 +31,10 @@ def __init__(self) -> None:
self.settings: Dict[str, Any] = {}
self.seen_macs: Set[str] = set()
self.seen_dhcp: Set[str] = set()
self.de_chatter: Dict[ # chatter protection (multiple packets less that chatter_delay)
self.debounce: Dict[ # bounce protection (repeated packets in less than bounce_delay from last event)
str, Dict[str, Any]
] = {}
self.chatter_delay = CHATTER_DELAY
self.bounce_delay = BOUNCE_DELAY

@staticmethod
def button_file_name(root: str) -> str:
Expand Down Expand Up @@ -91,18 +91,29 @@ def arp_handler(self, pkt: Packet) -> None:
print(f"Network request from unknown MAC {mac}")
self.seen_macs.add(mac)

def trigger(self, button: str) -> None:
"""Button press action."""
def is_bounced(self, button: str) -> bool:
"""Check if the button is pressed too recently and the press should be ignored.
If this is not bouncing we register the press in debounce dict.
"""
now = datetime.now()

if (
button in self.de_chatter
and self.de_chatter[button]["time"] + timedelta(seconds=self.chatter_delay)
> datetime.now()
button in self.debounce
and self.debounce[button]["time"] + timedelta(seconds=self.bounce_delay) > now
):
return True

self.debounce[button] = {"time": now}
return False

def trigger(self, button: str) -> None:
"""Button press action."""
if self.is_bounced(button):
print(
f'Chatter protection. Skip this network request from "{button}" as duplicate (see "chatter_delay" in settings).'
f'Bounce protection. Skip this network request from "{button}" as duplicate (see "bounce_delay" in settings).'
)
return
self.de_chatter[button] = {"time": datetime.now()}
print(f'button "{button}" pressed')
Action(self.settings).action(button)

Expand All @@ -114,7 +125,7 @@ def run(self) -> None:
"""Run server."""
self.buttons = self.load_buttons()
self.settings = self.load_settings()
self.chatter_delay = int(self.settings.get("chatter_delay", self.chatter_delay))
self.bounce_delay = int(self.settings.get("bounce_delay", self.bounce_delay))
print(f"amazon_dash started, loaded {len(self.buttons)} buttons")
self.sniff_arp()

Expand Down
8 changes: 4 additions & 4 deletions tests/test_amazon_dash.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import json
import os
from datetime import datetime
from amazon_dash import CHATTER_DELAY
from amazon_dash import BOUNCE_DELAY


def test_button_file_name(dash):
Expand Down Expand Up @@ -58,12 +58,12 @@ def test_load_buttons_no_file(mocker, dash):
@pytest.mark.parametrize(
"current_time, chatter_time, expected",
[
(datetime(2023, 9, 13, 12, 0, CHATTER_DELAY - 1), datetime(2023, 9, 13, 12, 0, 0), False),
(datetime(2023, 9, 13, 12, 0, BOUNCE_DELAY - 1), datetime(2023, 9, 13, 12, 0, 0), False),
(datetime(2023, 9, 13, 12, 0, 0), datetime(2023, 9, 13, 11, 54, 0), True),
],
)
def test_trigger_chatter_protection(mocker, dash, current_time, chatter_time, expected):
dash.de_chatter = {"button1": {"time": chatter_time}}
def test_trigger_debouncing(mocker, dash, current_time, chatter_time, expected):
dash.debounce = {"button1": {"time": chatter_time}}
mocker.patch('amazon_dash.datetime', MockDateTime(current_time))

mock_action = mocker.patch('amazon_dash.Action')
Expand Down

0 comments on commit 306e276

Please sign in to comment.