From d271f251dddbfc593af3ff4ce56c4022f03b3d88 Mon Sep 17 00:00:00 2001 From: carnage Date: Sun, 29 Dec 2019 08:28:11 +0000 Subject: [PATCH] Add advanced button handler (#42) * Add advanced button handler * Rename pylgbst/extras/advancedbutton.py to examples/advancedbutton/advancedbutton.py * Create README.md --- examples/advancedbutton/README.md | 40 +++++++++++++ examples/advancedbutton/advancedbutton.py | 73 +++++++++++++++++++++++ 2 files changed, 113 insertions(+) create mode 100644 examples/advancedbutton/README.md create mode 100644 examples/advancedbutton/advancedbutton.py diff --git a/examples/advancedbutton/README.md b/examples/advancedbutton/README.md new file mode 100644 index 0000000..024aa2c --- /dev/null +++ b/examples/advancedbutton/README.md @@ -0,0 +1,40 @@ +### Advanced button + +This example shows how you can add additional functionallity to the move hub button. + +It adds three new actions which you can use instead of the standard subscription to a button press: + +- Click - a single quick up/down press +- Double click - a double up/down press, second click must occur within .5 secs of first one +- Long press - a press and hold on the button for > .7 secs + +```python +from pylgbst.hub import MoveHub +from advancedbutton import AdvancedButton +import time + + +hub = MoveHub() +b = AdvancedButton(hub) + + +def clicked(): + print("button clicked") + + +def pressed(): + print("button pressed") + + +def doubleclicked(): + print("button double clicked") + + +b.click.subscribe(clicked) +b.double_click.subscribe(doubleclicked) +b.long_press.subscribe(pressed) + +time.sleep(120) +``` + +You can alter the timings using the two constants `DOUBLE_CLICK_TIME` and `LONG_PRESS_TIME` diff --git a/examples/advancedbutton/advancedbutton.py b/examples/advancedbutton/advancedbutton.py new file mode 100644 index 0000000..e8f62aa --- /dev/null +++ b/examples/advancedbutton/advancedbutton.py @@ -0,0 +1,73 @@ +import time +import threading + +DOUBLE_CLICK_TIME = 0.5 +LONG_PRESS_TIME = 0.7 + + +class AdvancedButton: + def __init__(self, hub): + self.state = 0 + self.last_pressed = 0 + self.press_time = None + self.hub = hub + self.hub.button.subscribe(self.pressed) + self.click = ButtonAction() + self.double_click = ButtonAction() + self.long_press = ButtonAction() + + def pressed(self, state): + if state == 2: + return + + press_time = time.time() + + if state == 1: + self.state = 1 + self.press_time = press_time + return + + if state == 0 and self.state == 1: + self.state = 0 + press_duration = press_time - self.press_time + else: + return + + if press_duration > LONG_PRESS_TIME: + # long press + self.long_press.notify() + return + + if (press_time - self.last_pressed) < DOUBLE_CLICK_TIME: + # double click + self.last_pressed = 0 + self.double_click.notify() + return + + # could be first of a double click, could be single click + self.last_pressed = press_time + + def timeout(): + time.sleep(DOUBLE_CLICK_TIME) + if self.last_pressed == press_time: + # not clicked while sleeping + # single click + self.click.notify() + + threading.Thread(target=timeout).start() + + +class ButtonAction: + def __init__(self): + self.subscribers = set() + + def subscribe(self, callback): + self.subscribers.add(callback) + + def unsubscribe(self, callback=None): + if callback in self.subscribers: + self.subscribers.remove(callback) + + def notify(self): + for subscriber in self.subscribers.copy(): + subscriber()